0 00:00:00,000 --> 00:00:06,000 Translated by visionNoob, KNU https://github.com/insurgent92/CS231N_17_KOR_SUB 1 00:00:10,512 --> 00:00:15,376 좋은 아침입니다. 12시 3분이군요. 수업을 진행하겠습니다. 2 00:00:15,376 --> 00:00:18,014 CS231n 12강입니다. 3 00:00:18,014 --> 00:00:21,840 오늘은 CNN의 시각화와 이해에 대해서 배워볼 것입니다. 4 00:00:21,840 --> 00:00:25,270 12강은 이미지 자료가 아주 많아서 아주 재미있는 수업이 될 것입니다. 5 00:00:25,270 --> 00:00:28,375 제가 가장 좋아하는 강의입니다. 6 00:00:28,375 --> 00:00:30,354 우선 몇 가지 공지사항을 전달해 드리겠습니다. 7 00:00:30,354 --> 00:00:39,544 프로젝트는 잘 진행하고 계신가요? 오늘 밤 까지 Canvas에 마일스톤을 제출해 주셔야 합니다. 8 00:00:39,545 --> 00:00:43,590 그리고 현재 중간고사를 채점 중입니다. 9 00:00:43,590 --> 00:00:49,537 아마도 채점 결과는 Gradescope를 통해서 이번 주 이내로 확인해 보실 수 있을 것입니다. 10 00:00:49,537 --> 00:00:54,987 지난 주에 여러분께서 Gradescope 가입과 관련해서 많이 혼란스러우셨을 것입니다. 11 00:00:54,988 --> 00:00:57,372 Piazza에서 이와 관련된 질문들을 많이 받았습니다. 12 00:00:57,372 --> 00:01:02,973 중간고사 채점 결과를 Gradescope를 통해서 발표하기로 결정했습니다. 관련 메일을 받으시면 잘 확인해 주시기 바랍니다. 13 00:00:59,530 --> 00:01:02,973 14 00:01:02,973 --> 00:01:07,412 그리고 지난 주 금요일에 과제 3이 출제 되었습니다. 15 00:01:05,047 --> 00:01:07,412 16 00:01:07,412 --> 00:01:11,088 과제 3은 지난 주 금요일부터 1주일 후인 26일 까지 입니다. 17 00:01:11,088 --> 00:01:14,444 과제3은 지난 해와 비교해서 완전히 달라졌습니다. 18 00:01:12,595 --> 00:01:14,444 19 00:01:14,444 --> 00:01:18,847 과제3을 예정보다 늦게 출제해 드려서 사과의 말씀 드립니다. 20 00:01:17,152 --> 00:01:18,847 21 00:01:18,847 --> 00:01:25,283 하지만 과제3은 아주 재밌을 것입니다. 오늘 강의에서 배운 내용들을 실제로 구현하게 될 것입니다. 22 00:01:20,272 --> 00:01:22,644 23 00:01:22,644 --> 00:01:25,283 24 00:01:25,283 --> 00:01:30,921 과제3을 하시려면 PyTorch/Tensor Flow 중에서 선택하시면 됩니다. 25 00:01:27,188 --> 00:01:29,575 26 00:01:29,575 --> 00:01:30,921 27 00:01:30,921 --> 00:01:34,512 이번 과제가 여러분들에게 의미있는 경험이 되었으면 좋겠습니다. 28 00:01:34,512 --> 00:01:37,273 그리고 주말 동안 많은 분들이 HyperQuest 활동을 해주셨습니다. 29 00:01:35,822 --> 00:01:37,273 30 00:01:37,273 --> 00:01:40,549 아주 놀라웠습니다. 리더보드가 어제 생겼는데 31 00:01:39,084 --> 00:01:40,549 32 00:01:40,549 --> 00:01:47,402 많은 분들이 Deep learning/ Neural network을 학습시키는 스킬들을 마음껏 뽐내 주셨습니다. 대단합니다. 33 00:01:42,568 --> 00:01:44,227 34 00:01:44,227 --> 00:01:46,063 35 00:01:46,063 --> 00:01:47,402 36 00:01:47,402 --> 00:01:55,118 HyperQuest의 많은 분들의 성원 가운데 마일스톤 제출기한이 HyperQuest와 겹치는 부분이 있었기 때문에 37 00:01:50,087 --> 00:01:52,811 38 00:01:52,811 --> 00:01:55,118 39 00:01:55,118 --> 00:01:58,591 Extra credit을 드리는 HyperQuest 마감일을 일요일까지 연장하기로 했습니다. 40 00:01:56,808 --> 00:01:58,591 41 00:01:58,591 --> 00:02:04,773 따라서 일요일 까지 HyperQuest를 12회 이상 실행하신 모든 분들에게 extra credit을 지급할 예정입니다. 42 00:02:02,279 --> 00:02:04,773 43 00:02:04,773 --> 00:02:11,200 그리고 리더보드의 상위권에 위치하신 분들은 조금 더 많은 credit을 받게될 것입니다. 44 00:02:07,394 --> 00:02:09,175 45 00:02:09,175 --> 00:02:11,200 46 00:02:11,200 --> 00:02:15,935 HyperQuest에 많은 관심에 감사드리며 아주 뜻깊은 시간인 것 같습니다. 47 00:02:13,081 --> 00:02:15,935 48 00:02:15,935 --> 00:02:17,844 마지막 공지사항은 poster session 관련 공지입니다. 49 00:02:17,844 --> 00:02:21,445 6월 6일에 poster session이 있습니다. 50 00:02:21,445 --> 00:02:25,932 6월 6일이 거의 확정일 것입니다. 정확한 시간은 기억이 안나지만, 6월 6일은 확실합니다. 51 00:02:22,872 --> 00:02:24,940 52 00:02:25,932 --> 00:02:31,897 종강 후 여행이나 인턴쉽을 준비하고 있는 많은 분들이 poster session 일정을 문의해 주셨습니다. 53 00:02:27,141 --> 00:02:29,310 54 00:02:29,310 --> 00:02:30,297 55 00:02:30,297 --> 00:02:31,897 56 00:02:31,897 --> 00:02:35,497 poster session은 6월 6일입니다. 57 00:02:33,247 --> 00:02:35,497 58 00:02:35,497 --> 00:02:41,171 공지사항에 대한 문의사항 있으십니까? 없으면 수업 진행하겠습니다. 59 00:02:39,241 --> 00:02:41,171 60 00:02:41,171 --> 00:02:48,161 지난 시간에는 다양한 Computer Vision Tasks를 살펴보았습니다. 61 00:02:42,578 --> 00:02:44,254 62 00:02:44,254 --> 00:02:46,259 63 00:02:46,259 --> 00:02:48,161 64 00:02:48,161 --> 00:02:54,318 우선 Semantic segmentation을 배웠습니다. 입력 이미지의 모든 픽셀에 레이블링을 하는 문제였습니다. 65 00:02:49,955 --> 00:02:52,035 66 00:02:52,035 --> 00:02:54,318 67 00:02:54,318 --> 00:02:58,225 하지만 Semantic Segmentation은 이미지 내의 객체들을 구분할 수 없었습니다. 68 00:02:56,131 --> 00:02:58,225 69 00:02:58,225 --> 00:03:00,773 그리고 Classification + Localization을 배웠습니다. 70 00:03:00,773 --> 00:03:06,539 이 문제는 이미지에 레이블을 부여하는 것 뿐만 아니라 객체의 정확한 위치의 BBox도 알아내야 했습니다. 71 00:03:02,558 --> 00:03:04,059 72 00:03:04,059 --> 00:03:06,539 73 00:03:06,539 --> 00:03:12,594 Classification + Localization 문제에서는 이미지 내에 알아내야 하는 객체의 수가 정해져 있었습니다. 74 00:03:08,041 --> 00:03:10,130 75 00:03:10,130 --> 00:03:12,594 76 00:03:12,594 --> 00:03:16,785 Classification + Localization을 응용해서 Pose recognition을 할 수 있었습니다. 77 00:03:14,424 --> 00:03:16,785 78 00:03:16,785 --> 00:03:20,222 사람의 관절의 위치를 regression 문제로 푸는 방법이었죠 79 00:03:18,836 --> 00:03:20,222 80 00:03:20,222 --> 00:03:27,102 Object Detection도 배웠습니다. 개, 고양이 처럼 고정된 category labels이 있었습니다. 81 00:03:22,235 --> 00:03:23,976 82 00:03:23,976 --> 00:03:25,851 83 00:03:25,851 --> 00:03:27,102 84 00:03:27,102 --> 00:03:32,769 그리고 이미지 내에 모든 객체의 위치에 BBox를 그려 넣어야 했습니다. 85 00:03:29,460 --> 00:03:31,196 86 00:03:31,196 --> 00:03:32,769 87 00:03:32,769 --> 00:03:37,063 Object Detection은 Classification + Localization 문제와는 다른 문제였습니다. 88 00:03:35,303 --> 00:03:37,063 89 00:03:37,063 --> 00:03:42,298 Object Detection 문제에서는 이미지 내에 객체의 수가 얼마나 있는지 미리 알 수 없었습니다. 90 00:03:38,783 --> 00:03:40,629 91 00:03:40,629 --> 00:03:42,298 92 00:03:42,298 --> 00:03:52,588 R-CNN, Fast R-CNN, Faster R-CNN 패밀리를 배웠습니다. 그리고 single shot detection 도 배웠죠(YOLO, SSD) 93 00:03:44,272 --> 00:03:48,100 94 00:03:48,100 --> 00:03:49,916 95 00:03:49,916 --> 00:03:52,588 96 00:03:52,588 --> 00:03:57,722 그리고 Instatnce Segmentation에 대해서도 간단하게 배워 보았습니다. 97 00:03:55,026 --> 00:03:57,722 98 00:03:57,722 --> 00:04:01,164 Semantic segmentation과 Object Detection을 결합시킨 방법이었습니다. 99 00:04:01,164 --> 00:04:04,934 Instance Segmentation의 목표는 우선 우리가 관심있는 카테고리에 속하는 모든 객체를 찾아내고 100 00:04:03,308 --> 00:04:04,934 101 00:04:04,934 --> 00:04:07,997 각 객체가 속하는 픽셀을 레이블링하는 문제였습니다. 102 00:04:07,997 --> 00:04:14,887 가령 이 예제에서는 2마리의 개와 1마리의 고양이가 있으며 객 객체가 속하는 픽셀을 레이블링해야 합니다. 103 00:04:11,339 --> 00:04:13,093 104 00:04:13,093 --> 00:04:14,887 105 00:04:14,887 --> 00:04:23,810 지난 시간에도 재미있는 Tasks들을 많이 다루긴 했지만 여러분이 프로젝트에 추가할만한 아주 많은 것들이 존재합니다. 106 00:04:17,437 --> 00:04:19,509 107 00:04:19,509 --> 00:04:21,284 108 00:04:21,284 --> 00:04:23,810 109 00:04:23,810 --> 00:04:27,081 오늘은 주제를 조금 바꿔보도록 하겠습니다. 110 00:04:25,645 --> 00:04:27,081 111 00:04:27,081 --> 00:04:30,578 과연 convolutional networks 내부에서는 어떤 일이 일어나고 있는 것일까요? 112 00:04:28,702 --> 00:04:30,578 113 00:04:30,578 --> 00:04:34,120 지금까지는 CNN을 어떻게 학습시킬 것인지를 배웠습니다. 114 00:04:32,445 --> 00:04:34,120 115 00:04:34,120 --> 00:04:37,503 그리고 다양한 문제를 풀기 위해서 CNN 아키텍쳐를 어떻게 설계하고 조합해야하는지를 배웠습니다. 116 00:04:35,916 --> 00:04:37,503 117 00:04:37,503 --> 00:04:42,653 자 이제 여러분이 해 볼만한 질문은 바로 CNN의 내부는 어떻게 생겼을지 입니다. 118 00:04:39,860 --> 00:04:42,653 119 00:04:42,653 --> 00:04:44,081 CNN은 이런 문제들을 어떻게 해결하는 것일까요? 120 00:04:44,081 --> 00:04:46,444 CNN이 어떤 종류의 Features를 찾고있는 것일까요? 121 00:04:46,444 --> 00:04:48,612 이와 같은 질문들 말입니다. 122 00:04:48,612 --> 00:04:53,399 지금까지는 ConvNets을 Black box라고 생각했습니다. 123 00:04:51,043 --> 00:04:53,399 124 00:04:53,399 --> 00:04:57,100 CNN의 한 쪽에서는 입력 이미지가 들어갑니다. 125 00:04:55,635 --> 00:04:57,100 126 00:04:57,100 --> 00:05:01,170 그리고 Conv Layers를 거치면서 아주 다양한 변환을 거치게 됩니다. 127 00:04:58,816 --> 00:05:01,170 128 00:05:01,170 --> 00:05:07,363 결국 CNN의 출력 값은 우리가 이해하고 해석할 수 있는 Class scores의 형태로 나오는 것입니다. 129 00:05:04,547 --> 00:05:07,363 130 00:05:07,363 --> 00:05:12,342 Class scores 뿐만 아니라 Bounding Box의 위치, Labeled pixels 와 같은 형태의 출력도 있을 것입니다. 131 00:05:09,865 --> 00:05:12,342 132 00:05:12,342 --> 00:05:15,933 그럼 CNN의 중간 과정에서는 무슨 일이 일어나는 것일까요? 133 00:05:13,307 --> 00:05:15,933 134 00:05:15,933 --> 00:05:18,567 CNN이 입력 이미지에서 찾고있는 것은 무엇일까요? 135 00:05:18,567 --> 00:05:24,364 ConvNets은 어떻게 동작할까요? CNN이 도대체 이미지에서 어떤 종류의 것들을 찾고있는 걸까요? 136 00:05:20,857 --> 00:05:22,023 137 00:05:22,023 --> 00:05:24,364 138 00:05:24,364 --> 00:05:29,327 CNN의 내부를 분석하려면 어떤 테크닉이 필요할까요? 139 00:05:25,867 --> 00:05:29,327 140 00:05:29,327 --> 00:05:34,522 우선 가장 만만하게 접근해 볼 수 있는 것은 첫 번째 Layer 입니다. 141 00:05:32,667 --> 00:05:34,522 142 00:05:34,522 --> 00:05:41,492 우선 AlexNet의 예시를 살펴보겠습니다. 143 00:05:37,508 --> 00:05:39,819 144 00:05:39,819 --> 00:05:41,492 145 00:05:41,492 --> 00:05:45,193 AlexNet의 첫 번째 Conv Layers에는 많은 필터들이 있습니다. 146 00:05:43,262 --> 00:05:45,193 147 00:05:45,193 --> 00:05:49,230 AlexNet의 각 Conv filter는 3 x 11 x 11의 형태를 취하고 있습니다. 148 00:05:49,230 --> 00:05:52,268 Conv filters는 sliding window로 이미지를 돕니다. 149 00:05:51,228 --> 00:05:52,268 150 00:05:52,268 --> 00:05:54,947 그리고 이미지의 일부 영역과 내적을 수행합니다. 151 00:05:54,947 --> 00:06:01,729 이렇게 필터의 가중치와 내적한 결과가 첫 번째 Conv Layer의 출력입니다. 152 00:05:56,909 --> 00:05:58,689 153 00:05:58,689 --> 00:06:01,729 154 00:06:01,729 --> 00:06:05,074 AlexNet의 첫 번째 레이어에는 64개의 filter가 있습니다. 155 00:06:05,074 --> 00:06:11,682 첫 번째 Conv Layer는 입력 이미지와 직접 내적을 수행하기 때문에 156 00:06:06,947 --> 00:06:08,780 157 00:06:08,780 --> 00:06:10,175 158 00:06:10,175 --> 00:06:11,682 159 00:06:11,682 --> 00:06:19,458 이 필터를 단순히 시각화시키는 것 만으로도 이 필터가 이미지에서 무엇을 찾고 있는지 알아낼 수 있습니다. 160 00:06:14,548 --> 00:06:17,697 161 00:06:17,697 --> 00:06:19,458 162 00:06:19,458 --> 00:06:30,201 AlexNet의 11x11x3 필터는 11x11x3 rgb 이미지로 쉽게 시각화할 수 있습니다. 163 00:06:22,576 --> 00:06:25,027 164 00:06:25,027 --> 00:06:28,461 165 00:06:28,461 --> 00:06:30,201 166 00:06:30,201 --> 00:06:35,305 필터가 총 64개 이므로 64개의 11x11 이미지를 시각화시킬 수 있습니다. 167 00:06:32,051 --> 00:06:35,305 168 00:06:35,305 --> 00:06:42,509 지금 보시는 이미지는 PyTorch Model zoo에서 가져온 pretrained model의 필터들입니다. 169 00:06:38,047 --> 00:06:40,982 170 00:06:40,982 --> 00:06:42,509 171 00:06:42,509 --> 00:06:51,065 AlexNet, ResNet-18, ResNet-101,DenseNet-121 의 첫 번째 Conv filter의 가중치들 입니다. 172 00:06:44,739 --> 00:06:45,985 173 00:06:45,985 --> 00:06:48,313 174 00:06:48,313 --> 00:06:51,065 175 00:06:51,065 --> 00:06:55,553 이를 통해서 이 필터들이 무엇을 찾고있는지 알 수 있습니다. 176 00:06:53,753 --> 00:06:55,553 177 00:06:55,553 --> 00:07:01,052 우선 가장 많이 찾는 것은 엣지성분 입니다. 흰/검으로 길게 늘어선 필터들이 보이실 것입니다. 178 00:06:59,015 --> 00:07:01,052 179 00:07:01,052 --> 00:07:09,475 다양한 각도와 위치에서의 보색(oppising colors)도 보입니다. 가령 초록색과 분홍색처럼 말이죠 180 00:07:04,487 --> 00:07:07,200 181 00:07:07,200 --> 00:07:09,475 182 00:07:09,475 --> 00:07:12,732 주황색과 파랑색의 보색도 보입니다. 183 00:07:12,732 --> 00:07:17,907 학습된 필터를 살펴보면 첫 강의에서 살펴본 hubel and wiesel의 실험이 떠오릅니다. 184 00:07:14,893 --> 00:07:16,221 185 00:07:16,221 --> 00:07:17,907 186 00:07:17,907 --> 00:07:24,978 인간의 시각 체계에서도 Oriented edges를 감지한다고 알려져 있습니다. 초기 레이어에서 말이죠 187 00:07:19,716 --> 00:07:22,271 188 00:07:22,271 --> 00:07:24,978 189 00:07:24,978 --> 00:07:31,566 CNN의 첫 번째 layer에서도 비슷한 일이 일어나는 것 같습니다. 190 00:07:26,946 --> 00:07:29,136 191 00:07:29,136 --> 00:07:31,566 192 00:07:31,566 --> 00:07:46,389 흥미롭게도, CNN을 어떤 모델/데이터로 학습하건 간에 첫 번째 레이어는 전부 다 이런 식으로 생겼다는 점입니다. 193 00:07:33,153 --> 00:07:35,631 194 00:07:35,631 --> 00:07:37,920 195 00:07:37,920 --> 00:07:40,594 196 00:07:40,594 --> 00:07:42,736 197 00:07:42,736 --> 00:07:44,990 198 00:07:44,990 --> 00:07:46,389 199 00:07:46,389 --> 00:07:51,539 입력 이미지에서 oriented edges 라던지 보색(opposing colors) 같은 것들을 찾는 것입니다. 200 00:07:48,676 --> 00:07:51,539 201 00:07:51,539 --> 00:07:53,696 질문 있나요? 202 00:08:04,215 --> 00:08:07,592 네. 이 이 이미지들을 CNN Layer의 학습된 가중치 입니다. 203 00:08:06,118 --> 00:08:07,592 204 00:08:15,766 --> 00:08:21,318 질문은 "필터의 가중치를 시각화한다고 해서 필터가 무엇을 찾고있는지 알 수 있는지" 입니다. 205 00:08:16,826 --> 00:08:18,998 206 00:08:18,998 --> 00:08:21,318 207 00:08:21,318 --> 00:08:25,045 이는 Templete Matching 이나 내적을 생각하시면 됩니다. 208 00:08:23,945 --> 00:08:25,045 209 00:08:25,045 --> 00:08:28,389 가령 여러분이 Templete vecter를 가지고있다고 해봅시다. 210 00:08:28,389 --> 00:08:35,044 이 Templete Vector와 임의의 데이터를 내적해서 어떤 Scaler output을 계산합니다. 211 00:08:31,125 --> 00:08:33,272 212 00:08:33,272 --> 00:08:35,044 213 00:08:35,044 --> 00:08:43,062 필터 값을 가장 활성화시키는 입력을 생각해보면 입력 값고 필터의 가중치 값이 동일한 경우입니다. 214 00:08:38,321 --> 00:08:40,289 215 00:08:40,289 --> 00:08:43,062 216 00:08:43,062 --> 00:08:52,506 내적을 생각해보면, 내적 값을 최대화 시키려면 동일한 값 두 개를 내적하는 것입니다. 217 00:08:45,564 --> 00:08:48,066 218 00:08:48,066 --> 00:08:49,736 219 00:08:49,736 --> 00:08:52,506 220 00:08:52,506 --> 00:08:57,902 그렇게 때문에 첫 번째 레이어의 가중치를 시각화시키면 첫 번째 레이어가 무엇을 찾고 있는지 알 수 있는 것입니다. 221 00:08:55,060 --> 00:08:56,323 222 00:08:56,323 --> 00:08:57,902 223 00:09:06,008 --> 00:09:10,052 그리고 이 첫 번쨰 레이어는 Convolutional Layer 입니다. 224 00:09:08,731 --> 00:09:10,052 225 00:09:10,052 --> 00:09:18,178 이미지를 입력으로 받는 CNN은 일반적으로 첫 번째 레이어가 Conv Layer입니다. 226 00:09:12,003 --> 00:09:13,808 227 00:09:13,808 --> 00:09:15,174 228 00:09:15,174 --> 00:09:16,525 229 00:09:16,525 --> 00:09:18,178 230 00:09:28,086 --> 00:09:32,118 다음 질문은 "네트워크의 중간에도 이런 시각화를 동일하게 적용할 수 있는지" 입니다. 231 00:09:29,006 --> 00:09:30,665 232 00:09:30,665 --> 00:09:32,118 233 00:09:32,118 --> 00:09:35,104 바로 다음 슬라이드가 그 내용입니다. :D 234 00:09:33,202 --> 00:09:35,104 235 00:09:35,104 --> 00:09:41,753 앞서 했던 동일한 시각화 기법을 중간 Conv Layers에 적용하면, 우리가 보고 해석하기 더 어렵습니다. 236 00:09:37,123 --> 00:09:39,767 237 00:09:39,767 --> 00:09:41,753 238 00:09:41,753 --> 00:09:45,081 지금 보시는 것이 동일한 시각화 기법을 적용한 것입니다. 239 00:09:45,081 --> 00:09:51,890 현재 보시는 슬라이드는 우리 웹사이트에 있는 작은 ConvNets demo network입니다. 240 00:09:49,278 --> 00:09:50,474 241 00:09:50,474 --> 00:09:51,890 242 00:09:51,890 --> 00:09:55,987 이 네트워크에서 첫 번째 레이어는 7 x 7 필터 16개 입니다. 243 00:09:52,702 --> 00:09:55,987 244 00:09:55,987 --> 00:10:00,842 앞선 슬라이드에서 시각화로 보여드렸던 첫 번째 레이어와 동일합니다. 245 00:09:58,263 --> 00:10:00,842 246 00:10:00,842 --> 00:10:06,583 이제는 두 번째 레이어의 가중치들을 살펴봅시다. 두 번째 레이어까지는 수 차례 Conv & ReLU를 거쳐야 합니다. 247 00:10:02,366 --> 00:10:04,491 248 00:10:04,491 --> 00:10:06,583 249 00:10:06,583 --> 00:10:10,629 두 번째 Conv Layer는 16채널의 입력을 받습니다. 250 00:10:08,185 --> 00:10:10,629 251 00:10:10,629 --> 00:10:15,116 그리고 20개의 7x7 conv filters가 있습니다. 252 00:10:15,116 --> 00:10:20,495 이 필터들은 직접적으로 이미지의 형태로 시각화시킬 수 없다는 문제점이 있습니다. 253 00:10:16,064 --> 00:10:18,660 254 00:10:18,660 --> 00:10:20,495 255 00:10:20,495 --> 00:10:23,846 어쨌든 시도는 해볼 수 있겠죠 256 00:10:23,846 --> 00:10:28,547 이 예시에서는 입력은 16 depth를 가지고 있습니다. 257 00:10:28,547 --> 00:10:40,924 그리고 Conv filters의 사이즈는 7 x 7 x 16 입니다. 이런 필터가 20개 있습니다. 258 00:10:30,286 --> 00:10:32,542 259 00:10:32,542 --> 00:10:34,388 260 00:10:34,388 --> 00:10:35,759 261 00:10:35,759 --> 00:10:38,072 262 00:10:38,072 --> 00:10:40,924 263 00:10:40,924 --> 00:10:47,498 여기서 문제점은 이 필터들을 직접 살펴보는 것 만으로는 이해할만한 정보를 얻기 힘들다는 점입니다. 264 00:10:44,035 --> 00:10:45,128 265 00:10:45,128 --> 00:10:47,498 266 00:10:47,498 --> 00:10:53,743 여기에 (Layer 2 weights) 두 번째 레이어를 시각화 시켰습니다. 16 x 7 x 7 필터를 시각화하기 위해서는 267 00:10:49,734 --> 00:10:53,743 268 00:10:53,743 --> 00:11:01,782 16개의 7 x 7 grayscale images로 나눠서 표현해야 합니다. 269 00:10:58,192 --> 00:11:01,782 270 00:11:01,782 --> 00:11:11,852 중간에 보이시는 Gray scale 이미지들이 바로 두 번째 레이어의 각 필터들의 가중치입니다. 271 00:11:03,284 --> 00:11:07,095 272 00:11:07,095 --> 00:11:08,898 273 00:11:08,898 --> 00:11:11,852 274 00:11:11,852 --> 00:11:21,046 두 번째 레이어의 출력이 총 20개 이므로 "7 x 7 이미지 16개"가 총 20개 있습니다. 275 00:11:14,473 --> 00:11:17,534 276 00:11:17,534 --> 00:11:21,046 277 00:11:21,046 --> 00:11:28,638 두 번째 레이어의 convolutional filters를 이미지로 시각화 해보면 이런 식의 특별한 구조들을 보실 수 있습니다. 278 00:11:22,871 --> 00:11:24,307 279 00:11:24,307 --> 00:11:26,709 280 00:11:26,709 --> 00:11:28,638 281 00:11:28,638 --> 00:11:32,128 그런데 아무리 자세히 봐도 이 필터가 무엇을 찾고 있는건지 적당한 Intuition을 얻기란 힘듭니다. 282 00:11:30,897 --> 00:11:32,128 283 00:11:32,128 --> 00:11:36,644 아무리 봐도 잘 모르겠는 이유는 이 필터들은 이미지와 직접 연결되어 있지 않기 떄문입니다. 284 00:11:35,099 --> 00:11:36,644 285 00:11:36,644 --> 00:11:41,851 두 번째 레이어의 필터들은 첫 번째 레이어의 출력과 연결되어 있습니다. 286 00:11:39,493 --> 00:11:41,851 287 00:11:41,851 --> 00:11:50,646 따라서 우리가 시각화한 내용은 "두 번째 레이어의 결과를 최대화시키는 첫 번째 레이어의 출력 패턴이 무엇인지" 입니다. 288 00:11:44,189 --> 00:11:46,684 289 00:11:46,684 --> 00:11:49,331 290 00:11:49,331 --> 00:11:50,646 291 00:11:50,646 --> 00:11:58,490 하지만 이미지의 관점에서 첫 번째 레이어의 출력이 어떻게 생겼는지 감을 잡고 해석하기한 쉽지 않습니다. 292 00:11:52,423 --> 00:11:53,860 293 00:11:53,860 --> 00:11:55,966 294 00:11:55,966 --> 00:11:58,490 295 00:11:58,490 --> 00:12:03,556 따라서 네트워크의 중간 레이어의 필터들이 무엇을 찾고있는지를 알아내려면 조금 더 fancy한 기법이 필요합니다. 296 00:12:00,893 --> 00:12:02,047 297 00:12:02,047 --> 00:12:03,556 298 00:12:03,556 --> 00:12:04,819 질문있나요? 299 00:12:09,189 --> 00:12:16,552 앞서 슬라이드에 있던 이미지들은 0-255 의 범위로 가중치를 normalize한 것입니다. 300 00:12:10,489 --> 00:12:13,456 301 00:12:13,456 --> 00:12:16,552 302 00:12:16,552 --> 00:12:22,983 실제 가중치들은 범위가 정해져있지 않습니다. 하지만 시각화를 위해서라면 스케일을 조정해야 합니다. 303 00:12:18,648 --> 00:12:19,885 304 00:12:19,885 --> 00:12:22,983 305 00:12:22,983 --> 00:12:31,892 그리고 필터만 시각화한 것이지 Bias는 고려하지 않았습니다. 따라서 이 시각화 결과를 있는 그대로 믿으면 안됩니다. 306 00:12:24,685 --> 00:12:26,409 307 00:12:26,409 --> 00:12:28,162 308 00:12:28,162 --> 00:12:30,423 309 00:12:30,423 --> 00:12:31,892 310 00:12:34,180 --> 00:12:38,391 자 이제는 마지막 레이어를 살펴봅시다. CNN의 마지막 레이어를 가지고 놀어봅시다. 311 00:12:35,237 --> 00:12:36,733 312 00:12:36,733 --> 00:12:38,391 313 00:12:38,391 --> 00:12:44,908 CNN의 마지막 레이어는 1000개의 클래스 스코어가 있습니다. 이는 학습 데이터의 predicted scores를 의미합니다. 314 00:12:40,698 --> 00:12:42,891 315 00:12:42,891 --> 00:12:44,908 316 00:12:44,908 --> 00:12:48,628 이 마지막 레이어 직전에는 Fully Connected Layer가 있습니다. 317 00:12:46,676 --> 00:12:48,628 318 00:12:48,628 --> 00:12:58,328 가령 AlesNet의 마지막 레이어는 이미지를 표현하는 4096-dim 특징벡터를 입력으로 최종 Class scores를 출력합니다. 319 00:12:49,962 --> 00:12:53,039 320 00:12:53,039 --> 00:12:55,516 321 00:12:55,516 --> 00:12:58,328 322 00:12:58,328 --> 00:13:07,967 CNN의 마지막 레이어에서 어떤 일이 일어나는 지를 알아보는 것도 시각화의 한 방법이 될 수 있습니다. 323 00:13:00,606 --> 00:13:02,787 324 00:13:02,787 --> 00:13:04,263 325 00:13:04,263 --> 00:13:06,520 326 00:13:06,520 --> 00:13:07,967 327 00:13:07,967 --> 00:13:18,687 이 방법은 많은 이미지로 CNN을 돌려서 각 이미지에서 나온 4096-dim 특징 벡터를 모두 저장힙니다. 328 00:13:09,022 --> 00:13:11,230 329 00:13:11,230 --> 00:13:13,110 330 00:13:13,110 --> 00:13:14,815 331 00:13:14,815 --> 00:13:17,174 332 00:13:17,174 --> 00:13:18,687 333 00:13:18,687 --> 00:13:26,075 앞선 방법에서는 첫 번째 Conv Layer를 시각화시켰지만 이제는 마지막 Hidden Layer를 시각화시킬 것입니다. 334 00:13:20,722 --> 00:13:23,219 335 00:13:23,219 --> 00:13:26,075 336 00:13:26,075 --> 00:13:29,791 여기에서 시도해볼 수 있는 방법 중 하나는 Nearest Neighbor를 이용한 방법입니다. 337 00:13:27,804 --> 00:13:29,791 338 00:13:29,791 --> 00:13:33,162 맨 왼쪽의 이미지는 Lecture 2에서 본 적 있으실 것입니다. 339 00:13:31,559 --> 00:13:33,162 340 00:13:33,162 --> 00:13:40,303 CiFAR-10 데이터들의 "이미지 픽셀 공간" 에서의 Nearest neighbors 였습니다. 341 00:13:36,045 --> 00:13:37,967 342 00:13:37,967 --> 00:13:40,303 343 00:13:40,303 --> 00:13:48,660 CIFAR-10으로 한 결과를 보시면 유사한 이미지를 잘 찾아내는 것을 알 수 있습니다. 344 00:13:41,996 --> 00:13:44,765 345 00:13:44,765 --> 00:13:46,500 346 00:13:46,500 --> 00:13:48,660 347 00:13:48,660 --> 00:13:58,917 맨 왼쪽 열이 CIFAR-10 으로 학습시킨 이미지입니다. 오른쪽 5열의 이미지는 Testset이죠 348 00:13:50,777 --> 00:13:52,350 349 00:13:52,350 --> 00:13:54,987 350 00:13:54,987 --> 00:13:57,239 351 00:13:57,239 --> 00:13:58,917 352 00:13:58,917 --> 00:14:02,446 가령 두 번째 행에 있는 흰색 강아지의 예를 들어보겠습니다. 353 00:14:00,185 --> 00:14:02,446 354 00:14:02,446 --> 00:14:11,643 픽셀 공간에서의 Nearest neighbors는 흰색 덩어리가 있으면 가깝다고 생각할 것입니다. 굳이 개가 아니라도 말이죠 355 00:14:04,523 --> 00:14:06,328 356 00:14:06,328 --> 00:14:08,321 357 00:14:08,321 --> 00:14:09,885 358 00:14:09,885 --> 00:14:11,643 359 00:14:11,643 --> 00:14:16,937 이런 식으로 거리가 가까운 이미지들을 시각화해 보는 방법도 시각화 기법이 될 수 있습니다. 360 00:14:14,268 --> 00:14:16,937 361 00:14:16,937 --> 00:14:27,107 다만 픽셀 공간에서 Nearest neighbors를 계산하는 것이 아니라 CNN에서 나온 4096-dim 특징 벡터 공간에서 계산합니다. 362 00:14:17,963 --> 00:14:19,952 363 00:14:19,952 --> 00:14:21,735 364 00:14:21,735 --> 00:14:24,507 365 00:14:24,507 --> 00:14:27,107 366 00:14:27,107 --> 00:14:29,987 오른쪽에 예제가 몇 가지 있습니다. 367 00:14:28,351 --> 00:14:29,987 368 00:14:29,987 --> 00:14:38,338 맨 왼쪽 열은 ImageNet Classification Dataset의 Test Set입니다. 369 00:14:32,069 --> 00:14:34,924 370 00:14:34,924 --> 00:14:38,338 371 00:14:38,338 --> 00:14:48,515 그리고 나머지 열 들은 AlexNet의 4096-dim 특징벡터에서 계산한 nearest neighbors 결과입니다. 372 00:14:41,253 --> 00:14:43,614 373 00:14:43,614 --> 00:14:46,863 374 00:14:46,863 --> 00:14:48,515 375 00:14:48,515 --> 00:14:52,941 이 결과를 보면 확실히 픽셀 공간에서의 nearest neighbors와는 아주 다릅니다. 376 00:14:51,010 --> 00:14:52,941 377 00:14:52,941 --> 00:14:58,375 "특징 공간에서의 nearest neighbors"의 결과를 보면 서로 픽셀 값의 차이가 큰 경우도 있습니다. 378 00:14:55,086 --> 00:14:57,111 379 00:14:57,111 --> 00:14:58,375 380 00:14:58,375 --> 00:15:03,031 서로 픽셀 값의 차이는 커도 특징 공간 내에서는 아주 유사한 특성을 지닌다는 것을 알 수 있습니다. 381 00:15:03,031 --> 00:15:10,484 가령 여기 두번째 줄에 코끼리의 예를 살펴봅시다. 코끼리는 왼쪽에 서있고 그 뒤에는 풀밭이 있습니다. 382 00:15:10,484 --> 00:15:17,307 테스트 셋의 3번째로 가까운 이미지를 살펴보면 코끼리가 오른쪽에 서 있습니다. 383 00:15:17,307 --> 00:15:26,942 아주 흥미롭습니다. 코끼리가 왼편에 서 있는 이미지와 오른편에 서 있는 이미지의 픽셀 값은 완전히 다를 것이기 때문입니다. 384 00:15:26,942 --> 00:15:32,554 하지만 네트워크가 학습한 특징 공간 내에서는 두 이미지는 아주 아까워집니다. 385 00:15:32,554 --> 00:15:37,975 이는 네트워크가 학습을 통해서 이미지의 semantic content한 특징들을 잘 포착해 낸 결과입니다. 386 00:15:37,975 --> 00:15:46,192 아주 놀라운 일이죠. 이처럼 Nearest neighbor를 통한 시각화 기법은 어떤 일이 일어나는지 살펴보기에 아주 좋습니다. 387 00:16:02,617 --> 00:16:04,630 [학생이 질문] 388 00:16:04,630 --> 00:16:13,942 기본적인 supervised learning 과정에서는 특징공간에서 서로 유사해야한다는 Loss는 없습니다. 389 00:16:13,942 --> 00:16:21,476 특징 공간에서 서로 유사해야한다고 말해주지 않았는데도 결국은 서로 가까워 진 것입니다. 390 00:16:21,476 --> 00:16:28,746 하지만 사람들이 "triplet/contrastive loss" 를 네트워크가 추가시켜서 학습하기도 합니다. 391 00:16:28,746 --> 00:16:37,253 이 losses를 통해 특징 공간에서의 계산이 가능하도록 가정과 제약조건을 마지막 레이어에 추가하는 것입니다. 392 00:16:37,253 --> 00:16:39,907 하지만 AlexNet의 경우에는 그런 장치가 없습니다. 393 00:16:44,931 --> 00:16:46,060 문제는 가장 가까운 것이 무엇인지... 394 00:16:46,060 --> 00:16:48,875 질문은 "마지막 레이어에 nearest neighbor를 적용하려면 어떻게 해야하는지" 입니다. 395 00:16:48,875 --> 00:16:51,432 우선 이미지를 네트워크에 통과시킵니다. 396 00:16:51,432 --> 00:16:57,670 뒤에서 두번째에 있는 히든 레이어는 4096-dim 벡터입니다. 397 00:16:57,670 --> 00:17:01,797 네트워크이 마지막 단에는 FC-Layer가 있었습니다. 398 00:17:01,797 --> 00:17:06,893 자 그럼 각 이미지들에 해당하는 4096-dim 벡터들을 전부 다 저장해 놓습니다. 399 00:17:06,894 --> 00:17:12,966 그리고 저장된 4096-dim 벡터들을 가지고 nearest neighbors를 계산합니다. 400 00:17:17,012 --> 00:17:19,171 수업이 끝나고 다시한번 말씀드리죠 401 00:17:19,171 --> 00:17:28,434 최종 레이어에서 어떤 일이 벌어지는지를 시각화하고자 할 때 "차원 축소"의 관점으로 볼 수도 있습니다. 402 00:17:28,435 --> 00:17:33,220 CS229를 수강하신 분들이라면 PCA에 대해서 들어본 적 있으실 것입니다. 403 00:17:33,220 --> 00:17:39,841 PCA는 4096-dim 과 같은 고차원 특징벡터들을 2-dim 으로 압축시키는 기법입니다. 404 00:17:39,841 --> 00:17:43,183 이 방법을 통해서 특징 공간을 조금 더 직접적으로 시각화시킬 수 있습니다. 405 00:17:43,183 --> 00:17:51,321 Principle Component Analysis(PCA) 로 이런 일을 할 수는 있지만 t-SNE라는 알고리즘이 더 파워풀합니다. 406 00:17:51,321 --> 00:17:54,656 t-SNE는 t-distributed stochastic neighbor embeddings 이라는 뜻입니다. 407 00:17:54,656 --> 00:18:03,137 많은 사람들이 특징공간을 시각화하기 위해서 사용하는 PCA보다는 조금 더 강력한 방법입니다. 408 00:18:03,137 --> 00:18:07,264 여기 t-SNE의 예시가 있습니다. 409 00:18:07,264 --> 00:18:13,231 MNIST를 t-SNE dimensionality reduction 를 통해 시각화한 모습입니다. 410 00:18:13,231 --> 00:18:17,521 MNIST는 0부터 9까지로 이루어진 손글씨 숫자 데이터셋입니다. 411 00:18:17,521 --> 00:18:22,226 MNIST의 각 이미지는 Gray scale 28x28 이미지입니다. 412 00:18:22,226 --> 00:18:32,020 여기에서는 t-SNE가 MNST의 28x28-dim 데이터를 입력으로 받습니다(raw pixels). 그리고 2-dim으로 압축합니다. 413 00:18:32,020 --> 00:18:37,096 그리고 압축된 2-dim 을 이용해서 MNIST를 시각화합니다. 414 00:18:37,096 --> 00:18:42,653 t-SNE로 MNIST를 시각화해보면 이런 식으로 자연스럽게 군집화된 모습을 볼 수 있습니다. 415 00:18:42,653 --> 00:18:47,532 각 군집이 MNIST의 각 숫자를 의미합니다. 416 00:18:47,532 --> 00:18:57,348 이런 식의 시각화 기법을 ImageNet을 분류하려고 학습시킨 네트워크의 마지막 레이어에도 적용해볼 수 있습니다. 417 00:18:57,348 --> 00:19:05,073 조금 더 자세히 말씀드리자면 엄청나게 많은 이미지들을 네트워크에 통과시킵니다. 418 00:19:05,073 --> 00:19:10,865 그리고 각 이미지에 대해서 최종 단의 4096-dim 특징 벡터들을 기록합니다. 419 00:19:10,865 --> 00:19:14,756 그러면 4096-dim 특징 벡터들을 아주 많이 모을 수 있을 것입니다. 420 00:19:14,756 --> 00:19:24,277 그리고 이 특징벡터들에 t-SNE을 적용하면 4096-dim에서 2-dim으로 압축됩니다. 421 00:19:24,277 --> 00:19:36,415 이를 통해 2-dim 특징 공간의 각 grid에 압축된 2-dum 특징들이 시각화시킵니다. 422 00:19:36,415 --> 00:19:43,417 이를 통해 학습된 특징 공간의 기학적인 모습을 어렴풋이 추측해 볼 수 있습니다. 423 00:19:43,417 --> 00:19:48,620 슬라이드의 이미지가 잘 안보이실 것입니다. 온라인에서 고해상도로 다시한번 살펴보시기 바랍니다. 424 00:19:48,620 --> 00:19:56,451 한번 살펴보자면 좌하단의 초록초록한 군집을 볼 수 있습니다. 이 곳에는 다양한 종류의 꽃들이 있습니다. 425 00:19:56,451 --> 00:20:01,800 또 다른 곳들에는 다양한 종류의 개들이 모여있고, 다양한 동물들끼리 모여있고, 다양한 지역들이 모여있습니다. 426 00:20:01,800 --> 00:20:06,192 이를 통해 우리가 학습시킨 특징 공간에는 일종의 불연속적인 의미론적 개념(semantic notion)이 존재하며 427 00:20:06,192 --> 00:20:11,597 t-SNE을 통한 dimensionality reduction version의 특징 공간을 살펴보며 그 공간을 조금이나마 느낄 수 있습니다. 428 00:20:11,597 --> 00:20:12,604 질문 있나요? 429 00:20:23,716 --> 00:20:29,793 한 이미지당 서로 다른 세 가지 정보가 존재합니다. 430 00:20:29,793 --> 00:20:31,308 1: 우선 (픽셀로 된) 원본 이미지가 있습니다. 431 00:20:31,308 --> 00:20:33,353 2: 그리고 4096-dim 벡터가 있습니다. (fc-layer의 출력) 432 00:20:33,353 --> 00:20:38,109 3: 그리고 t-SNE를 이용해 4096-dim 벡터를 2-dim 벡터로 변환시킨 값이 있습니다. 433 00:20:38,109 --> 00:20:49,547 결국 원본 이미지를 CNN으로 4096-dim으로 줄이고 이를 다시 t-SNE로 2-dim으로 줄였다고 보시면 되겠습니다. 434 00:20:49,547 --> 00:20:50,348 질문 있나요? 435 00:20:55,864 --> 00:20:59,255 질문은 t-SNE로 만든 이 2차원 공간에서 대강 얼마나 많은 데이터들을 표현할 수 있는지 입니다. 436 00:20:59,255 --> 00:21:06,080 정확히 얼마나 표현할 수 있는지 확신하긴 어렵습니다. t-SNE는 비선형 차원축소 기법이라 상당히 복잡한 성격을 지닙니다. 437 00:21:06,080 --> 00:21:10,259 다시 한번 확인해 봐야 겠지만 정확히 얼마나 표현할 수 있을지 잘 모르겠습니다. 438 00:21:10,259 --> 00:21:14,377 질문 있나요? 439 00:21:14,377 --> 00:21:17,038 질문은 "FC-layer가 아닌 더 상위 레이어에서도 이와 같은 시각화가 가능한지" 입니다. 440 00:21:17,038 --> 00:21:21,384 네 가능합니다. 하지만 안타깝게도 우리 강의자료에는 없네요. 죄송합니다. 441 00:21:21,384 --> 00:21:24,603 질문있나요? 442 00:21:35,559 --> 00:21:39,482 질문은 "이미지들이 차원축소 과정에서 이미지들이 서로 겹치지는 않은지" 입니다. 443 00:21:39,482 --> 00:21:40,902 네 물론 겹칠 수 있습니다. 444 00:21:40,902 --> 00:21:47,537 regular grid를 기준으로 nearest neighbor, 즉 각 grid point에 가장 가까운 이미지를 뽑아냅니다. 445 00:21:47,537 --> 00:21:54,792 따라서 이 시각화 기법이 특징 공간 분포의 모양을 보여주는 것은 아닙니다. 446 00:21:54,792 --> 00:22:03,122 t-SNE는 분포 자체를 보고자 함은 아닙니다. 그러한 특성을 다루는 몇 가지 다른 시각화 기법들이 존재합니다. 447 00:22:03,122 --> 00:22:07,713 네트워크의 중간에서 뽑은 특징들을 가지고 해볼 수 있는 다른 것들도 한번 살펴보겠습니다. 448 00:22:07,713 --> 00:22:13,856 앞서, 중간 레이어에 있는 가중치를 시각화한다고 해도 이를 해석하기는 쉽지 않다고 말씀드렸습니다. 449 00:22:13,856 --> 00:22:20,846 하지만 중간 레이어의 가중치가 아니라 Activation map을 시각화 해보면 일부 해석할 수 있는 것들을 볼 수 있습니다. 450 00:22:20,846 --> 00:22:28,603 다시 AlexNet의 예시를 살펴보겠습니다. 451 00:22:28,603 --> 00:22:35,668 AlexNet의 conv5의 특징은 128 x 13 x 13-dim tensor입니다. 452 00:22:35,668 --> 00:22:42,386 이 tensor는 128개의 13x13 2-dim gird로 볼 수 있습니다. 453 00:22:42,386 --> 00:22:49,741 따라서 이 13 x 13 ( x 1) 특징 맵을 그레이스케일 이미지로 시각화해 볼 수 있습니다. 454 00:22:49,741 --> 00:22:58,501 이를 시각화해보면 conv layer가 입력에서 어떤 특징을 찾고있는지를 짐작해볼 수 있습니다. 455 00:22:58,501 --> 00:23:03,306 지금 보시고있는 툴은 Jason Yasenski가 만든 아주 멋진 툴로 여러분도 다운로드받으실 수 있습니다. 456 00:23:03,306 --> 00:23:06,598 지금 동영상으로는 보여드리지 않겠지만 이 분의 웹사이트에 접속하시면 보실 수 있습니다. 457 00:23:06,598 --> 00:23:10,059 여기에서는 웹캠으로 받은 영상을 CNN에 통과시킵니다. 458 00:23:10,059 --> 00:23:17,279 그리고 실시간으로 중간의 각 특징 맵들을 시각화시켜서 각 레이어들이 무엇을 찾고있는지를 짐작해볼 수 있습니다. 459 00:23:17,279 --> 00:23:23,931 이 예시의 입력 이미지는 카메라 앞에 사람이 있는 영상입니다. 460 00:23:23,931 --> 00:23:28,192 중간 특징들의 대부분은 noisy하고 볼만한 게 없지만 461 00:23:28,192 --> 00:23:34,277 제가 초록색으로 표시한 특징맵을 보시면, (왼쪽에 더 크게 확대된 이미지도 있습니다.) 462 00:23:34,277 --> 00:23:41,103 이 특징맵은 사람의 얼굴에 활성화되는 것 같아 보입니다. 아주 재미있습니다. 463 00:23:41,103 --> 00:23:51,045 이 특징맵을 통해서, 분명 네트워크의 어떤 레이어에서는 사람의 얼굴을 찾고있는지 모른다는 것을 알 수 있습니다. 464 00:23:51,045 --> 00:23:54,132 아주 놀라운 발견입니다. 465 00:23:54,132 --> 00:23:55,517 질문있나요? 466 00:23:59,038 --> 00:24:04,957 질문은 "완전 새까만 특징 맵들"은 "Dead ReLU" 인지 입니다. 용어에 주의해야 합니다. 467 00:24:04,957 --> 00:24:09,539 대게 "Dead ReLU"라고 함은 모든 학습 데이터셋에 대해서 "Dead(활성화 되지 않음)" 을 의미합니다. 468 00:24:09,539 --> 00:24:14,701 이 예시의 경우에는 "특정 입력" 에 대해서 활성화되지 않았을 뿐입니다. 469 00:24:14,701 --> 00:24:15,702 질문있나요? 470 00:24:19,457 --> 00:24:22,538 질문은 "만약 ImageNet에 사람의 얼굴이 없다면 어떻게 네트워크가 사람의 얼굴을 인식할 수 있는지" 입니다. 471 00:24:22,538 --> 00:24:24,182 ImageNet의 사람은 아주 많이 등장합니다. 472 00:24:24,182 --> 00:24:29,020 물론 ImageNet Classification Chanllenge에의 1000개의 카테고리에 "사람"은 없습니다. 473 00:24:29,020 --> 00:24:34,906 많은 이미지들에 사람이 등잘하며, 다른 카테고리를 분류하더라도 사람이 등장한다는 특성은 유용한 신호일 수 있습니다. 474 00:24:34,906 --> 00:24:41,617 그리고 이는 정말 대단한 결과입니다. 분류 문제를 풀기에 유용한 특징들을 알아서 학습한 것이기 떄문입니다. 475 00:24:41,617 --> 00:24:47,483 가령 고양이만 분류하라고 했을 뿐인데, 고양이를 분류할 때 사람이 유용한 특징이라면 알아서 학습하는 것입니다. 대단한 것이죠. 476 00:24:50,346 --> 00:24:51,929 질문있나요? 477 00:24:55,192 --> 00:25:03,334 네트워크의 입력은 3 x 224 x 224 입니다. 그리고 여러 레이어를 통과할 것입니다. 478 00:25:03,334 --> 00:25:07,731 각 레이어는 3차원의 값을 반환합니다. (width x height x depth) 479 00:25:07,731 --> 00:25:10,476 이 3차원 덩어리(chunk)가 바로 네트워크 레이어가 출력하는 값입니다. 480 00:25:10,476 --> 00:25:18,155 그리고 이 3차원 덩어리를 "activation volume" 이라고 합니다. 481 00:25:18,155 --> 00:25:22,156 그리고 이 덩어리를 하나씩 잘라내면(slice) 그것이 바로 activation map 입니다. 482 00:25:34,426 --> 00:25:38,513 앞어 질문은 "입력 이미지가 K x K 라면 activation map이 K x K 인지" 였습니다. 483 00:25:38,513 --> 00:25:42,489 그렇지 않습니다. 네트워크 중간에 pooling 과 같은 sub sampling 과정이 있을 수 있기 때문입니다. 484 00:25:42,489 --> 00:25:47,756 하지만 일반적으로 activation map의 크기는 입력 이미지와 선형적인 관계를 갖습니다. 485 00:25:50,492 --> 00:25:55,625 자 그래서 중간 특징들을 시각화시킬 수 있는 또 다른 방법이 있습니다. 486 00:25:55,625 --> 00:26:03,453 어떤 이미지가 들어와야 각 뉴런들의 활성이 최대화되는지를 시각화해보는 방법입니다. 487 00:26:03,453 --> 00:26:08,605 이 예시에서도 다시 한번 AlexNet의 conv5 layer를 사용하겠습니다. 488 00:26:08,605 --> 00:26:10,926 이 활성화 볼륨 각각을 기억하십시오. 489 00:26:10,926 --> 00:26:15,738 AlexNet의 conv5는 128 x 13 x 13 한 덩어리의 activation volume을 갖습니다. 490 00:26:15,738 --> 00:26:19,644 우리는 이제 128개의 채널 중에 하나를 뽑을 것입니다. 여기에서는 17번째 채널을 선택했군요 491 00:26:19,644 --> 00:26:23,749 그리고 많은 이미지들을 CNN에 통과시킵니다. 492 00:26:23,749 --> 00:26:27,456 그리고 각 이미지의 conv5 features를 기록해 놓습니다. 493 00:26:27,456 --> 00:26:37,925 그리고나서 어떤 이미지가 17번째 특징 맵을 최대로 활성화시키는지를 살펴봅니다. 494 00:26:37,925 --> 00:26:45,161 그리고 현재 이 뉴런은 convolutional layer 입니다. 따라서 receptive field가 작은 편이죠 495 00:26:45,161 --> 00:26:49,239 각 뉴런이 전체 이미지를 보고있지는 않습니다. 이미지의 일부만을 보고있죠 496 00:26:49,239 --> 00:27:00,731 따라서 특정 레이어의 특징을 최대화시키는 이미지의 일부분(pathes)을 시각화시킬 것입니다. 497 00:27:00,731 --> 00:27:06,177 그리고 특정 레이어의 활성화 정도를 기준으로 패치들을 정렬시키면 되겠습니다. 498 00:27:06,177 --> 00:27:12,575 자 여기 오른쪽에 예시가 있습니다. 이 네트워크의 이름은 "fully.." 사실 어떤 네트워크인지는 크게 중요하진 않습니다. 499 00:27:12,575 --> 00:27:16,380 어쨌든 여기에 지금 보이는 패치들이 바로 해당 레이어의 활성을 최대화시키는 패치들입니다. 500 00:27:16,380 --> 00:27:22,500 각 행에 있는 패치들이 하나의 뉴런에서 나온 것입니다. 501 00:27:22,500 --> 00:27:28,280 각 패치들은 데이터셋에서 나온 패치들을 정렬한 값들이고 502 00:27:28,280 --> 00:27:30,611 이 패치들이 해당 뉴런의 활성을 최대화시키는 패치들입니다. 503 00:27:30,611 --> 00:27:35,698 패치의 특징을 통해서 해당 뉴런이 무엇을 찾고있는지 짐작해 볼 수 있습니다. 504 00:27:35,698 --> 00:27:39,998 가령 맨 윗 행을 보시면 어떤 동그란 모양을 찾고있다는 것을 알 수 있습니다. 505 00:27:39,998 --> 00:27:44,621 눈 같은 것들이죠. 눈이 많네요. 그리고 파란색 동그란 패치도 있군요 506 00:27:44,621 --> 00:27:51,303 이로 미루어, 네트워크 레이어의 어떤 뉴런은 입력 영상에서 어떤 푸르스름하고 둥근 물체를 찾고있는 것 같습니다. 507 00:27:51,303 --> 00:27:56,200 그리고 여기 중간에 보시면 뉴런이 다양한 색상의 문자를 찾는 뉴런도 있습니다. 508 00:27:56,200 --> 00:28:02,201 또는 다양한 colors & orientations을 가진 휘어진 엣지를 찾는 뉴런이 있다는 것도 알 수 있습니다. 509 00:28:06,246 --> 00:28:09,199 제가 여기에서 용어를 조금 느슨하게 사용한 감이 있습니다. 510 00:28:09,199 --> 00:28:13,970 한 뉴런은 conv5 activation map의 하나의 scaler 값을 의미합니다. 511 00:28:13,970 --> 00:28:19,283 conv5 는 convolutional layer 이기 때문에 한 채널안의 모든 뉴런들은 모두 같은 가중치를 공유합니다. 512 00:28:19,283 --> 00:28:26,451 각 채널 당 하나의 conv filter가 있고 이에 상응하는 많은 뉴런들이 있습니다.(activation map) 513 00:28:26,451 --> 00:28:32,532 Convolution의 특성 상 우리는 앞서 보여드린 patch들을 이미지의 모든 곳에서 추출해 낼 수 있습니다. 514 00:28:32,532 --> 00:28:38,721 그리고 밑의 예시들은 동일 네트워크의 더 깊은 레이어에서 뉴런들을 최대로 활성화시키는 패치들입니다. 515 00:28:38,721 --> 00:28:42,294 이들은 더 깊은 레이어로부터 왔기 때문에 Receptive field가 훨씬 더 넓습니다. 516 00:28:42,294 --> 00:28:44,851 이들은 입력 영상에서 훨씬 더 큰 patch들을 기준으로 찾고 있습니다. 517 00:28:44,851 --> 00:28:49,213 실제로 예시들을 살펴보면 입력 이미지에서 더 큰 구조들(structures)을 찾고있음을 알 수 있습니다. 518 00:28:49,213 --> 00:28:56,445 두 번째 행을 살펴보면 이는 사람, 또는 사람의 얼굴을 찾고 있는것 같아 보입니다. 519 00:28:56,445 --> 00:29:06,410 세 번째 행은 카메라의 일부분을 찾고 있는듯 합니다. 이처럼 조금 더 큰 것들을 찾고 있는 것입니다. 520 00:29:06,410 --> 00:29:11,885 그리고 우리는 조금 더 재밌는 실험을 해볼 수 있습니다. 이는 Zeiler and Fergus가 ECCV'14에 발표한 논문입니다. 521 00:29:11,885 --> 00:29:14,062 이 논문은 "occlusion experiment" 에 관한 논문입니다. 522 00:29:14,062 --> 00:29:21,659 이 실험에서 알고자하는 것은 입력의 어떤 부분이 분류를 결정짓는 근거가 되는지에 관한 실험입니다. 523 00:29:21,659 --> 00:29:25,339 우선 입력 이미지를 받습니다. 가령 이 예시의 경우는 코끼리입니다. 524 00:29:25,339 --> 00:29:32,486 그리고 이미지의 일부를 가립니다. 그리고 가린 부분을 데이터셋의 평균 값으로 채워버립니다. 525 00:29:32,486 --> 00:29:39,583 그리고 가려진 이미지를 네트워크에 통과시키고 네트워크가 이 이미지를 예측한 확률을 기록합니다. 526 00:29:39,583 --> 00:29:44,752 그리고 이 가림 패치( occluded patch)를 전체 이미지에 대해 돌아가면서(slide) 같은 과정을 반복합니다. 527 00:29:44,752 --> 00:29:53,699 오른쪽의 히트맵은 이미지를 가린 patch의 위치에 따른 네트워크의 예측 확률의 변화를 의미합니다. 528 00:29:53,699 --> 00:29:59,952 이 실험의 아이디어는, 만약 이미지의 일부를 가렸는데 네트워크의 스코어의 변화가 크게 발생한다면 529 00:29:59,952 --> 00:30:04,809 가려진 바로 그 부분이 분류를 결정짓는데 아주 중요한 부분이었다는 사실을 짐작할 수 있는 것입니다. 530 00:30:04,809 --> 00:30:11,420 여기에 "occlusion experiment"을 수행한 세 가지 예시가 있습니다. 531 00:30:11,420 --> 00:30:14,456 가장 밑의 Go-kart의 예시를 살펴봅시다. 532 00:30:14,456 --> 00:30:23,077 빨간색 지역은 확률 값이 낮고, 노란색 지역은 확률 값이 높음을 의미합니다. 533 00:30:23,077 --> 00:30:30,348 앞쪽의 Go-kard를 가렸을 때 Go-kart에 대한 확률이 아주 많이 감소함을 볼 수 있습니다. 534 00:30:30,348 --> 00:30:38,419 이를 통해 네트워크가 분류를 결정할 때 실제로 go-kart를 아주 많이 고려한다는 사실을 알 수 있습니다. 535 00:30:38,419 --> 00:30:39,589 질문 있나요? 536 00:30:47,473 --> 00:30:49,780 질문은 "배경의 경우는 어떻게 된 것인지" 입니다. (go-kart 이미지의 배경을 가려도 확률이 감소) 537 00:30:49,780 --> 00:30:56,020 현재 이미지가 너무 작아서 잘 안보이실 수도 있습니다만 뒷쪽 배경에 Go-kart 트랙과 다른 Go-kart들이 있습니다. 538 00:30:56,020 --> 00:31:00,395 제 생각에는 뒷쪽의 go-kart를 가리는 경우에도 점수에 영향을 미치는 것으로 사료됩니다. 539 00:31:00,395 --> 00:31:04,628 또는 수평선(horizon)의 영향일지도 모르겠습니다. Go-kart를 검출하는데 수평선이 유용한 특징일지도 모릅니다. 540 00:31:04,628 --> 00:31:08,976 사실은 이렇게 해석하기 힘든 경우도 있습니다. 어쨌든 이 방법도 아주 훌륭한 시각화 방법입니다. 541 00:31:08,976 --> 00:31:10,118 질문 있나요? 542 00:31:20,486 --> 00:31:23,500 첫 번째 질문이 뭐였죠? 543 00:31:30,731 --> 00:31:36,802 이 예제의 경우에 이미지 한장에 대해서 현재 이미지의 모든 부분을 조금씩 가려본 것입니다. 544 00:31:36,802 --> 00:31:38,777 두 번 질문은 "이 시각화 방법이 학습에 어떻게 유용한지" 입니다. 545 00:31:38,777 --> 00:31:42,982 학습 하는데 직접적으로 유용하지는 않습니다. 여기에서 얻는 정보를 학습 과정에 집어 넣을 수는 없습니다. 546 00:31:42,982 --> 00:31:49,341 다만 "사람"이 네트워크가 무엇을 하고 있는지를 이해할 수 있는 도구일 뿐입니다. 547 00:31:49,341 --> 00:31:54,296 결국 이런 시각화는 네트워크의 성능을 높히려는 목적이 아니라 "여러분이 이해" 함이 목적입니다. 548 00:31:54,296 --> 00:31:57,890 그리고 이와 관련된 또 다른 아이디어가 있습니다. "Saliency Map" 과 관련된 아이디어입니다. 549 00:31:57,890 --> 00:32:00,534 여러분이 앞으로 과제에서 보게될 것입니다. 550 00:32:00,534 --> 00:32:02,578 이 경우에도 같은 질문이 있습니다. 551 00:32:02,578 --> 00:32:07,831 입력 이미지가 들어옵니다. 이 경우에는 "개" 입니다. 그리고 이 이미지를 "개" 라고 예측했을 떄, 552 00:32:07,831 --> 00:32:11,796 우리가 알고싶은 것은 네트워크가 픽셀들을 보고서 이미지를 "개" 라고 분류했는지 입니다. 553 00:32:11,796 --> 00:32:19,452 앞서 특정 픽셀을 가리는(masking) 방법도 있었습니다만 Saliency Maps은 조금 다른 접근법을 취합니다. 554 00:32:19,452 --> 00:32:25,354 이 방법은 몇해 전 Karen Simonenian의 논문에서 나온 비교적 간단한 방법입니다. 555 00:32:25,354 --> 00:32:31,694 이 방법은 입력 이미지의 각 픽셀들에 대해서, 예측한 클래스 스코어의 그레디언트를 계산하는 방법입니다. 556 00:32:31,694 --> 00:32:36,042 이 방법은 일종의 "1차 근사적 방법"으로 어떤 픽셀이 영향력있는지를 알려줍니다. 557 00:32:36,042 --> 00:32:43,963 입력 이미지의 각 픽셀에 대해서, 우리가 그 픽셀을 조금 바꿨을 때 클래스 스코어가 얼마나 바뀔까요? 558 00:32:43,963 --> 00:32:50,496 이 질문은 어떤 픽셀이 "개"를 분류하는데 있어서 어떤 픽셀들이 필요한지알 수 있는 또 다른 방법이 될 수 있습니다. 559 00:32:50,496 --> 00:32:59,356 이 방법을 통해 "개" 이미지의 Saliency map을 만들어보면 "개"의 윤곽이 나타남을 알 수 있습니다. 560 00:32:59,356 --> 00:33:04,985 이는 네트워크가 이미지에서 어떤 픽셀들을 찾고 있는지를 짐작할 수 있습니다. 561 00:33:04,985 --> 00:33:11,675 이 방법은 다른 이미지들에도 적용해보면 네트워크가 올바른 지역을 보고있다는 것을 알 수 있습니다. 562 00:33:11,675 --> 00:33:13,360 좀 위안이 되는 것이죠 563 00:33:13,360 --> 00:33:14,462 질문 있나요? 564 00:33:17,407 --> 00:33:21,916 질문은 "사람들이 Saliency Maps을 semantic segmentation에도 사용하는지" 입니다. 565 00:33:21,916 --> 00:33:26,741 네 맞습니다. (웃음) 여러분들은 정말 최고입니다. 566 00:33:26,741 --> 00:33:29,513 semantic segmentation은 Karen의 논문에 또 다른 주제로 실려있습니다. 567 00:33:29,513 --> 00:33:38,925 아이디어, segmentation 레이블 없이 Saliency Maps 만 가지고 semantic segmentation을 수행할 수 있다는 것입니다. 568 00:33:38,925 --> 00:33:43,908 이들은 Grabcut Segmentation Algorithm을 이용합니다. Grabcut에 대해서는 더 자세하게 말씀드리지는 않겠습니다. 569 00:33:43,908 --> 00:33:47,772 Grabcut은 간단히 말해 interactive segmentation algorithm 입니다. 570 00:33:47,772 --> 00:33:55,697 이 Saliency Map과 Grabcut을 잘 조합하면 이미지 내에서 객체를 Segmentation할 수 있습니다. 571 00:33:55,697 --> 00:34:00,326 아주 멋진 아이디어입니다. 하지만 그렇게 잘 되지는 않습니다. 572 00:34:00,326 --> 00:34:07,182 supervision을 가지고 학습을 시키는 네트워크에 비해서는 훨씬 더 안좋습니다. 573 00:34:07,182 --> 00:34:13,458 실용적인지는 잘 모르겠지만 작동한다는 것 자체가 정말 놀랍습니다. 574 00:34:13,458 --> 00:34:19,025 supervision으로 segmentation을 학습시킨 모델보다는 훨씬 안좋지만 말이죠 575 00:34:19,025 --> 00:34:23,791 또 다른 아이디어로는 guided back propagation이 있습니다. 576 00:34:23,791 --> 00:34:30,001 이번에 할 질문은, 어떤 한 이미지가 있을 떄 577 00:34:30,001 --> 00:34:37,420 이제는 클래스 스코어가 아니라 네트워크의 중간 뉴런을 하나 고릅니다. 578 00:34:37,420 --> 00:34:44,199 그리고 입력 이미지의 어떤 부분이, 내가 선택한 중간 뉴런의 값에 영향을 주는지를 찾는 것이죠 579 00:34:44,199 --> 00:34:49,059 이 경우에도 앞서 했던 방법처럼 Saliency Map을 만들어볼 수 있을 것입니다. 580 00:34:49,059 --> 00:34:53,466 이 경우에는 이미지의 각 픽셀에 대한 "클래스 스코어"의 그래디언트를 계산하는 것이 아니라 581 00:34:53,466 --> 00:34:58,815 입력 이미지의 각 픽셀에 대한 네트워크 중간 뉴런의 그레디언트를 계산합니다. 582 00:34:58,815 --> 00:35:05,832 이를 통해 어떤 픽셀이 해당 뉴런에 영향을 주는 지 알 수 있습니다. 583 00:35:05,832 --> 00:35:08,342 이 경우에도 평범한 back propagation을 이용합니다. 584 00:35:08,342 --> 00:35:15,093 하지만 back propagation 과정에서 조금의 트릭을 가미하면 조금 더 깨끗한 이미지를 얻을수 있습니다. 585 00:35:15,093 --> 00:35:21,393 이를 "guided back propagation" 이라고 합니다. Zeilerand Fergus의 2014년 논문입니다. 586 00:35:21,393 --> 00:35:24,203 이번 시간에 이에 대해 더 깊게는 들어가지 않겠지만 587 00:35:24,203 --> 00:35:30,220 이 방법(guided backprop)은 backprop 시 ReLU를 통과할 때 조금의 변형을 가해줍니다. 588 00:35:30,220 --> 00:35:37,254 ReLU의 그레디언트의 부호가 양수 이면 그대로 통과시키고 부호가 음수이면 backprop하지 않는 방법입니다. 589 00:35:37,254 --> 00:35:46,948 이로인해 전체 네트워크가 실제 그레디언트를 이용하는 것이 아니라 "양의 부호인 그레디언트" 만을 고려하게 됩니다. 590 00:35:46,948 --> 00:35:53,614 이 방법이 왜 좋은지는 해당 논문을 각자 읽어보시기 바랍니다. 591 00:35:53,614 --> 00:36:01,649 실험 결과를 보면, guided backprop이 그냥에 비해 훨씬 더 선명하고 좋은 이미지를 얻을 수 있음을 알 수 있습니다. 592 00:36:01,649 --> 00:36:07,223 이 이미지들은 입력 이미지에 어떤 픽셀들이 특정 뉴런에 영향을 미치는지를 알려줍니다. 593 00:36:07,223 --> 00:36:12,467 앞서 슬라이드에서 "maximally activating patches" 파트에서 이와 비슷한 시각화기법을 살펴봤었습니다. 594 00:36:16,488 --> 00:36:20,174 "maximally activating patches" 기법 외에도 595 00:36:20,174 --> 00:36:27,604 "guided backpropagation" 이라는 방법을 통해서 패치의 어떤 부분이 뉴런에 영향을 미치는지 알 수 있습니다. 596 00:36:27,604 --> 00:36:37,139 맨 상당의 예를 살펴봅시다. 이미지들을 살펴보면 이 뉴런이 아마도 둥그런 것들을 찾고있음을 짐작해볼 수 있습니다. 597 00:36:37,139 --> 00:36:42,028 guided backprob 결과(왼쪽)를 살펴보면 방금 전 우리가 짐작했던 직관을 어느정도 확신할 수 있습니다. 598 00:36:42,028 --> 00:36:49,218 실제로 이미지 상의 둥근 부분들이 뉴런의 실제 값에 영향을 미치고 있음을 직접 확인할 수 있기 때문입니다. 599 00:36:49,218 --> 00:36:56,514 이렇게 guided backprob은 중간 레이어가 무엇을 찾고 있는지를 이해하기 위한 영상을 합성하는데 아주 유용합니다. 600 00:36:56,514 --> 00:37:05,108 하지만 guided backprob이나 saliency maps을 계산하는 방법들은 고정된 입력 이미지에 대한 연산을 수행할 뿐입니다. 601 00:37:05,108 --> 00:37:12,882 이 방법들은 "고정된" 입력 이미지, 또는 입력 패치의 어떤 부분이 해당 뉴런에 영향을 미치는지를 말해줍니다. 602 00:37:12,882 --> 00:37:19,110 그렇다면 입력 이미지에 의존적이지 않은 방법은 없을까요? 603 00:37:19,110 --> 00:37:24,641 해당 뉴런을 활성화시킬 수 있는 어떤 "일반적인" 입력 이미지가 있을까? 란 질문을 할 수 있습니다. 604 00:37:24,641 --> 00:37:29,118 이에 대한 질문은 "Gradient ascent" 라는 방법이 해답을 제시해줄 수 있습니다. 605 00:37:29,118 --> 00:37:34,903 우리는 지금까지 Loss를 최소화시켜 네트워크를 학습시키기 위해 Gradient decent를 사용했습니다. 606 00:37:34,903 --> 00:37:40,552 하지만 여기에서는 네트워크의 가중치들을 전부 고정시킵니다. 607 00:37:40,552 --> 00:37:50,932 그리고 Gradient ascent를 통해 중간 뉴런 혹은 클래스 스코어를 최대화 시키는 이미지의 픽셀들을 만들어냅니다. 608 00:37:50,932 --> 00:37:58,333 Gradient ascent는 네트워크의 가중치를 최적화하는 방법이 아닙니다. 가중치들은 모두 고정되어 있습니다. 609 00:37:58,333 --> 00:38:07,104 대신 뉴런, 또는 클래스 스코어가 최대화될 수 있도록 입력 이미지의 픽셀 값을 바꿔주는 방법입니다. 610 00:38:07,104 --> 00:38:10,475 이 방법에는 regularization term이 필요합니다. 611 00:38:10,475 --> 00:38:19,078 우리는 지금까지 regularization terms의 역할을 가중치들이 학습 데이터로의 과적합을 방지하기 위함으로 배웠습니다. 612 00:38:19,078 --> 00:38:27,109 이 경우에도 유사합니다. 생성된 이미지가 특정 네트워크의 특성에 완전히 과접합 되는 것을 방지하기 위함입니다. 613 00:38:27,109 --> 00:38:34,664 regularization term을 추가함으로서, 우리는 생성된 이미지가 두 가지 특성을 따르길 원하는 것입니다. 614 00:38:34,664 --> 00:38:39,269 하나는 이미지가 특정 뉴런의 값을 최대화시키는 방향으로 생성되길 원하는 것이고 615 00:38:39,269 --> 00:38:42,111 그리고 다른 하나는 이미지가 자연스러워 보여야 한다는 것입니다. 616 00:38:42,111 --> 00:38:46,485 생성된 이미지가 자연 영상에서 일반적으로 볼 수 있는 이미지이길(statistics) 원하는 것입니다. 617 00:38:46,485 --> 00:38:52,936 이런 류의 regularization term의 목적은 생성된 이미지가 비교적 자연스럽도록 강제하는 역할입니다. 618 00:38:52,936 --> 00:38:57,116 앞으로 다양한 regulaizer들을 살펴보겠습니다. 619 00:38:57,116 --> 00:39:04,371 Gradient Ascent는 비교적 간단한 방법입니다. 과제 3에서 여러분이 직접 구현해보실 수 있을 것입니다. 620 00:39:04,371 --> 00:39:10,410 Gradient Ascent를 위해서는 초기 이미지가 필요합니다. 이 이미지는 zeros, uniform, noise 등으로 초기화시켜줍니다. 621 00:39:10,410 --> 00:39:19,922 초기화를 하고나면 이미지를 네트워크에 통과시키고 여분이 관심있는 뉴런의 스코어를 계산합니다. 622 00:39:19,922 --> 00:39:26,643 그리고 이미지의 각 픽셀에 대한 해당 뉴런 스코어의 그레디언트를 계산하여 back prop을 수행합니다. 623 00:39:26,643 --> 00:39:33,897 여기에서는 Gradient Ascent를 이용해서 이미지 픽셀 자체를 업데이트합니다. 해당 스코어를 최대화시키려 하겠죠 624 00:39:33,897 --> 00:39:38,786 이 과정을 계속 반복하고나면 아주 멋진 이미지가 탄생합니다. 625 00:39:38,786 --> 00:39:42,311 여기에서도 이미지에 대한 regularizer를 언급하지 않을수 없습니다. 626 00:39:42,311 --> 00:39:49,428 여기에서는 단순하게 생성된 이미지에 대한 L2 norm을 계산해서 더해줍니다. 627 00:39:49,428 --> 00:39:51,466 사실 L2 norm을 추가하는 것 자체에 큰 의미가 있는 것은 아닙니다. 628 00:39:51,466 --> 00:40:01,764 Gradient Ascent와 같은 이미지 생성과 관련된 방법들의 초창기 문헌에서 종종 보이는 regularizer 중 하나일 뿐입니다. 629 00:40:01,764 --> 00:40:12,153 이 네트워크를 학습시켜보면, 가령 왼쪽 상당의 덤벨의 스코어를 최대화시키는 이미지가 생성됩니다. 630 00:40:12,153 --> 00:40:14,820 그리고 생성된 이미지를 살펴보면 631 00:40:14,820 --> 00:40:19,726 잘 안보이실 수도 있지만, 여러 덤벨 모양이 생성되었음을 알 수 있습니다. 632 00:40:19,726 --> 00:40:23,162 여러 덤벨들이 이곳 저곳에 중첩되어 있는 모양입니다. 633 00:40:23,162 --> 00:40:29,111 그리고 컵의 생성된 이미지를 보면 아주 다양한 컵들이 충첩되어 있는 이미지를 볼 수 있습니다. 634 00:40:29,111 --> 00:40:30,466 달마시안의 예가 정말 끝내줍니다. 635 00:40:30,466 --> 00:40:35,478 달마시안의 특징이라고 할 수 있는 검정/흰색 반점 무늬를 볼 수 있습니다. 636 00:40:35,478 --> 00:40:40,388 레몬의 경우에는 얼룩 얼룩한 노란색이 보입니다. 637 00:40:40,388 --> 00:40:43,539 여기 몇 가지 예제가 더 있습니다. 거위의 경우도 정말 놀랍습니다. 638 00:40:43,539 --> 00:40:46,514 키트 여우(kit fox)도 정말 키트 여우같아 보입니다. 639 00:40:46,514 --> 00:40:47,454 질문 있나요? 640 00:40:55,528 --> 00:40:57,929 질문은 "왜 이미지들이 무지개 색인지" 입니다. 641 00:40:57,929 --> 00:41:02,434 이 시각화 방법을 이용해서 실제 색상을 시각화하려면 상당히 까다롭습니다. 642 00:41:02,434 --> 00:41:06,693 실제 모든 이미지들은 0에서 255 사이의 값들로 이루어져야 합니다. 643 00:41:06,693 --> 00:41:10,395 이는 constrained optimization 문제입니다. 644 00:41:10,395 --> 00:41:15,721 하지만 Gradient ascent와 같은 일반적인 방법들은 제약조건이 없는(unconstrained) 경우입니다. 645 00:41:15,721 --> 00:41:21,848 따라서 여러분이 Projected gradient descent 와 같은 알고리즘을 사용하고 마지막에 rescale한 경우라면 646 00:41:21,848 --> 00:41:27,799 시각화 할 때 나타나는 색상과 관련해서는 너무 크게 신경쓸 필요 없습니다. 647 00:41:27,799 --> 00:41:28,702 질문 있나요? 648 00:41:32,801 --> 00:41:36,846 질문은 "아무 regularizer도 사용하지 않으면 어떻게 되는지" 입니다. 649 00:41:36,846 --> 00:41:44,860 그렇게 해도 클래스 스코어를 최대화시키는 어떤 이미지가 생성되기는 할 것입니다. 650 00:41:44,860 --> 00:41:48,522 하지만 그 이미지는 아무것도 아닌 것 처럼 보일 것입니다. 램덤 노이즈처럼 보일 뿐입니다. 651 00:41:48,522 --> 00:41:54,538 그렇긴 해도 그 이미지 자체가 가지는 아주 흥미로운 특징이 있습니다. 이는 나중에 더 자세히 배울 것입니다. 652 00:41:54,538 --> 00:42:00,913 어쩃든 이 이미지를 가지고는 네트워크가 어떤 것들을 찾고 있는지를 이해하기는 힘듭니다. 653 00:42:00,913 --> 00:42:09,607 따라서 이를 위해서는 regularizer를 추가해서 이미지가 조금 더 자연스럽게 생성되도록 하는 편이 좋습니다. 654 00:42:09,607 --> 00:42:10,471 질문 있나요? 655 00:42:34,416 --> 00:42:38,492 질문은 "multimodality를 다루는 다른 방법은 없는지"입니다. (클래스 내에서도 다양한 mode가 있음.) 656 00:42:38,492 --> 00:42:44,847 당연히 있습니다. 현재 시각화에 대한 본격적인 이야기는 이제 시작입니다. 657 00:42:44,847 --> 00:42:51,517 시각화의 다른 접근법들은 regularizer를 더욱 향상시키고 이미지를 더 잘 시각화시키는 방법에 관한 것입니다. 658 00:42:51,517 --> 00:42:58,621 Jason Yesenski, et al의 논문이 있습니다. 이들은 아주 인상적인 regularizers를 추가했습니다. 659 00:42:58,621 --> 00:43:00,924 L2 norm constraint은 여전히 있습니다. 660 00:43:00,924 --> 00:43:06,213 그리고 최적화 과정에 이미지에 주기적으로 가우시안 블러를 적용합니다. 661 00:43:06,213 --> 00:43:12,441 그리고 주기적으로 값이 작은 픽셀들은 모두 0으로 만듭니다. 662 00:43:12,441 --> 00:43:14,694 낮은 기울기의 픽셀 값 중 일부는 0으로 설정됩니다. 그레디언트가 작은 값들도 모두 0으로 만듭니다. 663 00:43:14,694 --> 00:43:17,559 이는 일종의 projected Gradient descent 라고 볼 수 있습니다. 664 00:43:17,559 --> 00:43:24,555 생성된 이미지를 더 좋은 특성을 가진 이미지 집합으로 주기적으로 매핑시키는 방법입니다. (밑에 세가지 방법으로) 665 00:43:24,555 --> 00:43:28,241 가령 가우시안 블러와 같은 스무딩 연산을 통해서죠 666 00:43:28,241 --> 00:43:32,870 이 방법을 이용하면 훨씬 더 보기 좋은 이미지를 생성할 수 있습니다. 훨씬 더 깔끔합니다. 667 00:43:32,870 --> 00:43:38,553 홍학은 조금 더 홍학처럼 생겼습니다. 딱정벌레도 더 잘 보입니다. 668 00:43:38,553 --> 00:43:41,695 검은 백조도 검은 백조처럼 잘 보입니다. 669 00:43:41,695 --> 00:43:48,211 그 중에 당구대가 상당히 인상적입니다. 확실히 당구대의 구조가 선명합니다. 670 00:43:48,211 --> 00:43:55,209 이처럼 조금 괜찮은 regularizer들을 추가하게 되면 생성되는 이미지가 조금 더 깔끔해질 수 있습니다. 671 00:43:55,209 --> 00:44:01,038 이 과정은 최종 스코어에만 적용하는게 아니라 중간 뉴런에도 적용해볼 수 있습니다. 672 00:44:01,038 --> 00:44:10,111 "당구대" 클래스의 스코어를 최대화시키는 것이 아니라 중간의 뉴런을 최대화시키는 이미지를 생성해볼 수도 있습니다. 673 00:44:10,111 --> 00:44:11,118 질문 있나요? 674 00:44:16,743 --> 00:44:19,393 질문은 "이 예제의 네가지 이미지가 무엇인지" 입니다. 675 00:44:19,393 --> 00:44:21,794 우선 이 이미지는 처음에 램덤 초기화된 이미지입니다. 676 00:44:21,794 --> 00:44:25,681 따라서 이 네 개의 이미지들은 서로 다르게 램덤으로 초기화된 입력 이미지입니다. 677 00:44:28,106 --> 00:44:36,113 다시 수업으로 돌아가서, 앞서 클래스 스코어에 적용했던 과정은 네트워크의 중간 뉴런을 최대화시키는 과정에 동일하게 적용됩니다. 678 00:44:36,113 --> 00:44:40,174 이를 통해서 중간 뉴런이 무엇을 찾고있는지 짐작해볼 수 있습니다. 679 00:44:40,174 --> 00:44:44,605 가령 네번째 레이어의 경우에는 나선형의 무언가를 찾고있는 것 같습니다. 680 00:44:44,605 --> 00:44:49,703 또 어떤 뉴런은 애벌레를 찾는 것 같아 보입니다. 정확이 무엇인지는 구별하기 힘들군요 681 00:44:49,703 --> 00:44:56,585 여기 예제 이미지가 큰 이미지일수록 receptive fileds 가 더 큰 뉴런들입니다. 682 00:44:56,585 --> 00:44:58,664 Receptive field가 클수록 이미지 패치 내에 더 큰 곳을 볼 수 있습니다. 683 00:44:58,664 --> 00:45:03,549 이런 뉴런들은 입력 이미지에서 더 큰 구조와 더 복잡한 패턴을 찾는 경향이 있습니다. 684 00:45:03,549 --> 00:45:04,802 아주 멋집니다. 685 00:45:07,499 --> 00:45:15,559 사람들이 이 시각화 방법이 이미지의 특징들을 잘 살리는 것에 아주 열광했습니다. 686 00:45:15,559 --> 00:45:23,697 방금 전 누군가가 질문해주신 multimodality 를 이 논문에서 아주 잘 다루고 있습니다. 687 00:45:23,697 --> 00:45:29,849 이 논문에서는 최적화 과정 속에 multimodality를 아주 명시적으로 다루고 있습니다. 688 00:45:29,849 --> 00:45:35,254 각 클래스마다 클러스터링 알고리즘을 수행합니다. 689 00:45:35,254 --> 00:45:42,667 한 클래스 내 서로 다른 모드들 끼리 다시 한번 클래스가 나뉩니다. 그리고 나뉜 모드들과 가까운 곳으로 초기화를 해주는 것이죠 690 00:45:42,667 --> 00:45:45,890 이 방법을 통해서 multimodality를 다룰 수 있는 것입니다. 691 00:45:45,890 --> 00:45:51,675 직관적으로 보면, 가령 여기 있는 여덟개의 이미지는 모두 식료품점(grocery store) 입니다. 692 00:45:51,675 --> 00:45:56,401 가장 상위의 이미지들은 선반 위에 전시된 물건들을 클로즈업 한 것 같아 보입니다. 693 00:45:56,401 --> 00:45:59,068 이들의 레이블은 "식료품 점" 입니다. 694 00:45:59,068 --> 00:46:04,221 그리고 하단의 이미지들은 사람들이 식료품점을 돌아다니고 있는 모슴인 것 같습니다. 695 00:46:04,221 --> 00:46:06,085 이 또한 식료품점으로 레이블링됩니다. 696 00:46:06,085 --> 00:46:08,073 하지만 이 둘은 아주 다르게 생겼습니다. 697 00:46:08,073 --> 00:46:10,988 많은 클래스들이 이렇게 multimodality를 가지고 있습니다. 698 00:46:10,988 --> 00:46:17,648 이미지를 생성할 때 이런 식으로 multimodality를 명시하게 되면 아주 좋은 (다양한) 결과를 얻을 수 있게 됩니다. 699 00:46:17,648 --> 00:46:22,569 예제를 조금 더 살펴보도록 하죠. 여러 클래스의 이미지를 합성해 보았습니다. 700 00:46:22,569 --> 00:46:31,840 피망, 카르둔, 딸기, 잭오랜턴 등을 볼 수 있습니다. 이미지가 아주 잘 생성되었습니다. 701 00:46:31,840 --> 00:46:38,177 다음 장은 깊게 들어가지는 않겠습니다만 이 방법은 훨씬 더 놀라운 방법입니다. 702 00:46:38,177 --> 00:46:43,623 이 방법은 이미지를 이쁘게 생성해 내기 위해서 훨씬 더 강력한 사전 정보(prior)를 이용합니다. 703 00:46:43,623 --> 00:46:48,921 여기 보이는 이미지들이 모두 ImageNet의 특정 클래스를 최대화하는 이미지를 생성해 낸 것입니다. 704 00:46:48,921 --> 00:46:59,020 기본 아이디어는 입력 이미지의 픽셀을 곧장 최적화하는 것 대신에 FC6를 최적화하는 것입니다. 705 00:46:59,020 --> 00:47:03,342 이를 위해서는 feature inversion network 등을 사용해야 하지만 자세히 들어가진 않겠습니다. 706 00:47:03,342 --> 00:47:05,290 관심있으신 분들은 논문을 읽어보시기 바랍니다. 아주 놀라운 방법입니다. 707 00:47:05,290 --> 00:47:11,905 요점은 이런 이미지 생성 문제에서 사전 지식(priors)를 추가하게 된다면 708 00:47:11,905 --> 00:47:16,662 아주 리얼한 이미지를 만들어낼 수 있다는 것입니다. 709 00:47:18,951 --> 00:47:23,839 이 방법도 여러분들이 시도해볼만한 아주 좋은 방법이 될 수 있습니다. 어쨋건, 710 00:47:23,839 --> 00:47:29,893 이미지 픽셀의 그레디언트를 이용해서 이렇게 이미지를 합성하는 방법은 아주 강력합니다. 711 00:47:29,893 --> 00:47:34,288 이를 통해 시도해볼 수 있는 아주 재미있는 것은 바로 네트워크를 속이는 이미지(fooling image)를 만드는 것입니다. 712 00:47:34,288 --> 00:47:43,362 우선 아무 이미지나 하나 고릅니다. 가령 코끼리 이미지를 골랐다고 해봅시다. 713 00:47:43,362 --> 00:47:49,418 그리고 네트워크가 이 이미지는 코알라 라고 분류하도록 이미지를 조금씩 바꿉니다. 714 00:47:49,418 --> 00:47:57,064 이렇게 코끼리 이미지를 조금씩 바꾸다보면 네트워크는 이 이미지를 코알라라고 분류해 버립니다. 715 00:47:57,064 --> 00:48:05,931 여러분이 혹시라도 코끼리가 갑자기 귀여운 귀를 가진 코알라로 변신하는 모습을 상상할 지 모르곘습니다만 716 00:48:05,931 --> 00:48:09,241 사실은 그런 일은 일어나지 않습니다. 이점이 아주 놀라운 점입니다. 717 00:48:09,241 --> 00:48:17,377 코끼리 사진을 가지고 코알라로 분류하도록 이미지를 바꿔보면 718 00:48:17,377 --> 00:48:24,853 실제로는 두 번째 이미지 처럼 보입니다. 네트워크는 두 번째 이미지를 코알라로 분류합니다. 우리에게는 별반 차이가 없습니다. 719 00:48:24,853 --> 00:48:28,016 아주 수상하기도(fishy) 하면서 놀랍기도 합니다. 720 00:48:28,016 --> 00:48:34,114 밑에 예제가 하나 더있습니다. 배 인것 같은데 ImageNet 클래스로는 Schooner(범선) 입니다. 721 00:48:34,114 --> 00:48:37,170 이제 네트워크가 아이팟으로 분류하도록 합니다. 722 00:48:37,170 --> 00:48:41,881 두 번째 이미지를 보면 우리에게는 똑같이 배인데 네트워크는 아이팟이라고 인식하고 있습니다. 723 00:48:41,881 --> 00:48:46,260 두 이미지 사이의 픽셀 값의 차이는 거의 없습니다. 724 00:48:46,260 --> 00:48:52,025 우리는 픽셀 값의 차이에서 코알라나 아이팟의 특징이라고는 찾아볼 수 없습니다. 725 00:48:52,025 --> 00:48:58,924 그저 랜덤한 패턴의 노이즈로 보일 뿐입니다. 그렇다면 질문은 "무슨 일이 일어난 것일까요?", "어떻게 이런게 가능한 것일까요?" 726 00:48:58,924 --> 00:49:03,635 굿조만한 우리 수업 게스트로 Ian Goodfellow를 초청할 예정입니다. 727 00:49:03,635 --> 00:49:08,068 Ian Goodfellow가 와서 이와관련한 현상을 조금 더 자세히 설명해 줄 것입니다. 아주 재밌을 것입니다. 728 00:49:08,068 --> 00:49:11,006 하지만 여기에서는 더 이상 언급하지 않겠습니다. 왜냐하면 여러분들의 과제이기 떄문이죠 729 00:49:11,006 --> 00:49:11,595 질문 있나요? 730 00:49:16,320 --> 00:49:20,050 질문은 "학습 데이터로도 네트워크를 속일 수 있는지" 입니다. 731 00:49:20,050 --> 00:49:27,214 이와 관련된 모든 것들은 Ian이 와서 소개해줄 것입니다. Ian Goodfellow가 와서 강연 내내 다룰 것입니다. 732 00:49:27,214 --> 00:49:28,885 질문 있나요? 733 00:50:00,608 --> 00:50:03,478 질문은 "왜 우리가 이딴거(stuff)에 관심을 가져야 하는 것인지" 734 00:50:03,478 --> 00:50:08,685 제가 질문을 조금 거칠게 표현했습니다. 죄송합니다. 735 00:50:24,573 --> 00:50:32,027 질문은 "중간 뉴런을 이해하는 것이 어떻게 최종 클래스 분류를 이해하는데 도움을 줄 수 있는지" 입니다. 736 00:50:32,027 --> 00:50:38,921 사실 이런 식으로 중간 레이어를 시각화하는 방법들은 딥러닝의 비판에 대한 반응에서 유래합니다. 737 00:50:38,921 --> 00:50:43,011 딥러닝의 비판이라 함은 "딥러닝 이라는 블랙박스를 가진건 알겠어, 738 00:50:43,011 --> 00:50:47,350 - 그리고 그걸 그레디언트로 잘 학습시켜서 좋은 결과가 나오는건 알겠는데, 사실 결과를 믿진 못하겠어 739 00:50:47,350 --> 00:50:51,272 딥러닝의 결과가 어떻게 나왔는지를 당신조차 이해할수 없잖아?" 와 같은 질문이죠 740 00:50:51,272 --> 00:51:01,530 이런 많은 시각화 기법들은 왜 딥러닝이 분류 문제를 더 잘 푸는지를 사람들이 이해하기 위해 고안되었습니다. 741 00:51:01,530 --> 00:51:07,721 가령, 딥러닝이 아닌 다른 기계학습 기법들을 생각해보면 742 00:51:07,722 --> 00:51:10,493 가령 선형 모델의 경우가 일반적으로 해석하기 훨씬 더 수월합니다. 743 00:51:10,493 --> 00:51:17,457 각 가중치를 보고 입력 특징들 중 어떤 부분이 얼마나 모델이 결정을 내리는데 영향을 미치는지 해석하기 용이합니다. 744 00:51:17,458 --> 00:51:19,459 Random forest와 같은 dectision tree를 보면 말이죠. 745 00:51:19,459 --> 00:51:27,442 이런 기계학습 기법들이 블랙박스인 CNN보다는 훨씬 더 자연스럽고 해석하기도 쉽습니다. 746 00:51:27,442 --> 00:51:33,520 딥러닝에 대한 앞서 언급한 비판들에 대한 대안으로 시각화 기법들이 등장했습니다. "그래 모델이 복잡하긴 하지, 747 00:51:33,520 --> 00:51:37,263 하지만 들춰보면 해석 가능한 것들이 있다구!" 라고 말하는 것입니다. 748 00:51:37,263 --> 00:51:42,201 딥러닝 모델이 아무렇게나 분류하는 것이 아니라 의미있는 행동을 하고 있음을 증명하려는 것입니다. 749 00:51:44,891 --> 00:51:50,989 이미지에 그레디언트를 업데이트하는 방식으로 가능한 재미있는 아이디어가 하나 더 있습니다. "DeepDeram" 입니다. 750 00:51:50,989 --> 00:51:55,592 작년 Google에서 나온 아주 재미있는 블로그 포스팅이 있었습니다. 751 00:51:55,592 --> 00:52:00,859 DeepDream의 "과학적 가치"의 측면에서 보자면 그저 "재미" 만을 위한 것입니다. 752 00:52:00,859 --> 00:52:04,284 DeepDream의 목적은 "재미있는 이미지를 만드는 것" 입니다. 753 00:52:04,284 --> 00:52:10,186 부가적으로 모델이 이미지의 어떤 특징들을 찾고 있는지를 짐작할 수도 있습니다. 754 00:52:10,186 --> 00:52:15,275 DeepDeram에서는 입력 이미지를 CNN의 중간 레이어를 어느정도 통과시킵니다. 755 00:52:15,275 --> 00:52:17,035 그리고 back prop을 할 차례입니다. 756 00:52:17,035 --> 00:52:20,742 해당 레이어의 그레디언트를 activation 값으로 설정합니다. 757 00:52:20,742 --> 00:52:25,427 그리고 back prob을 하여 이미지를 업데이트합니다. 이 과정을 계속 반복합니다. 758 00:52:25,427 --> 00:52:31,682 네트워크에 의해 검출된 해당 이미지의 특징들을 증폭시키려는 것으로 해석할 수 있습니다. 759 00:52:31,682 --> 00:52:35,875 해당 레이어에 어떤 특징들이 있던지 그 특징들을 그레디언트로 설정하면 760 00:52:35,875 --> 00:52:40,010 이는 네트워크가 이미지에서 이미 뽑아낸 특징들을 더욱 증폭시키는 역학을 하는 것입니다. 761 00:52:40,010 --> 00:52:46,918 그리고 이는 해당 레이어에서 나온 특징들의 L2 norm을 최대화시키는 것으로 볼 수 있습니다. 762 00:52:46,918 --> 00:52:55,999 DeepDream의 코드는 아주 심플합니다. 이는 여러분의 과제에 포함되어 있습니다. 763 00:52:55,999 --> 00:53:00,785 여러분이 앞으로 과제를 통해 접하겠지만 여기에는 몇 가지 트릭이 존재합니다. 764 00:53:00,785 --> 00:53:04,443 트릭 중 하나는 그레이언트를 계산하기에 앞서 이미지를 조금씩 움직이는 것입니다.(jitter) 765 00:53:04,443 --> 00:53:11,187 원본 이미지를 그대로 네트워크에 통과시키는 것 대신에 이미지를 두 픽셀 정도 이동시킵니다. 766 00:53:11,187 --> 00:53:19,540 이는 regularizer 역할을 해서 자연스럽고 부드러운 이미지를 만들어줍니다. 767 00:53:19,540 --> 00:53:26,653 그리고 여기에 L1 Normalization도 들어갑니다. 이는 이미지 합성 문제에서 아주 유용한 트릭입니다. 768 00:53:26,653 --> 00:53:33,843 그리고 픽셀 값을 한번 클리핑(Clipping) 해주기도 합니다. 이미지라면 값이 0-255 사이에 있어야만 합니다. 769 00:53:33,843 --> 00:53:39,335 이는 일종의 projected gradient decent인데 실제 이미지가 존재할 수 있는 공간으로 매핑시키는 방법입니다. 770 00:53:39,335 --> 00:53:46,215 이렇게 하늘 이미지를 가지고 알고리즘을 수행시키면 이처럼 아주 재미있는 결과를 보실 수 있습니다. 771 00:53:46,215 --> 00:53:52,614 하늘에 조그만한 특징들이 보이실 것입니다. 이들을 앞선 과정을 통해 증폭된 것들입니다. 772 00:53:52,614 --> 00:53:59,007 돌연변이 동물같은 것들이 나타났습니다. 나선 모양의 것들도 나타났습니다. 773 00:53:59,007 --> 00:54:04,296 다양한 종류의 건축물과 자동차도 나타났습니다. 모든 것들이 아주 흥미로운 결과입니다. 774 00:54:04,296 --> 00:54:08,743 나타난 특징들 중에 사람들이 이름을 지어낸 것들도 있습니다. 775 00:54:08,743 --> 00:54:12,133 아주 많이 나타난 것 중 하나가 "Admiral dog" 입니다. 776 00:54:12,133 --> 00:54:16,033 "돼지 달팽이 (pig snail), "낙타 새"(Camel-bird), "개 물고기"(dog-fish) 도 있습니다. 777 00:54:16,033 --> 00:54:22,771 이 모든것들이 아주 흥미롭습니다만, 이러한 시각화에 "개" 가 아주 빈번하게 등장한다는 것은 778 00:54:22,771 --> 00:54:26,249 이 네트워크를 학습시킨 데이터와 관련이 있습니다. 779 00:54:26,249 --> 00:54:30,786 이 네트워크는 ImageNet Classification 데이터셋으로 학습시켰습니다. 1000개의 카테고리가 있습니다. 780 00:54:30,786 --> 00:54:32,915 그런데, 그 중 200개의 카테고리가 개입니다. 781 00:54:32,915 --> 00:54:44,027 따라서 시각화된 결과에 "개"와 관련된 것들이 자주 나오는 것은 당연합니다. 782 00:54:44,027 --> 00:54:47,327 그리고 다른 레이어를 가지고 만들어보면 색다른 결과를 보실 수도 있습니다. 783 00:54:47,327 --> 00:54:52,708 이 예제의 경우 더 얕은 층의 레이어로 만든 이미지입니다. 앞서 보여드린 예제가 조금 더 깊은 층의 레이어로 만들었었죠 784 00:54:52,708 --> 00:54:57,791 더 얕은 층으로 만들어보면, 엣지나, 소용돌이 무늬와 같은 것들을이 보입니다. 785 00:54:57,791 --> 00:55:01,766 얕은 레이어로 DeepDream을 수행하면 보이는 것들입니다. 786 00:55:01,766 --> 00:55:08,346 DeepDream에 멀티 스케일을 가미해서 오랫동안 돌려보면 다음과 같은 아주아주 놀라운 것들을 볼 수 있습니다. 787 00:55:08,346 --> 00:55:14,631 여기에서는 멀티 스케일 프로세싱을 수행합니다. 작은 이미지로 DeepDream을 수행하고 점점 이미지 크기를 늘려나갑니다. 788 00:55:14,631 --> 00:55:19,893 이런 식으로 점점 더 큰 이미지에 DeepDream을 수행하는 반복적인 과정을 거치는데, 789 00:55:19,893 --> 00:55:25,699 가장 큰 최종 스케일로 수행하고 나면 다시 처음부터 이 과정을 반복 수행합니다. 790 00:55:25,699 --> 00:55:28,126 그 결과 이런 놀라운 이미지를 얻을 수 있습니다. 791 00:55:28,126 --> 00:55:31,454 지금 보시는 이미지는 ImageNet으로 학습시킨 네트워크로 만든 이미지입니다. 792 00:55:31,454 --> 00:55:35,216 다른 데이터셋으로도 만들어 볼 수 있습니다. 가령 MIT Paces Dataset으로도 해볼 수 있겠죠 793 00:55:35,216 --> 00:55:40,224 1,000 카테고리의 객체(ImageNet) 대신에 200가지의 다양한 장면을 가진 데이터셋입니다. 794 00:55:40,224 --> 00:55:42,663 이 데이터셋에는 가령 침실, 부엌 과 같은 장면이 있습니다. 795 00:55:42,663 --> 00:55:50,868 MIT place로 학습시킨 네트워크를 가지고 DeepDream을 수행하면, 이와 같은 멋있는 시각화 이미지를 얻을 수 있습니다. 796 00:55:50,868 --> 00:55:59,491 이제는 "개 달팽이, Admiral dogs" 와 같은 것들 대신에 일본식 건축물의 지붕과 같은 모양이라던지 797 00:55:59,491 --> 00:56:02,104 다양한 "다리(bridges)", "산맥(mountatin ranges" 과 같은 것들이 보입니다. 798 00:56:02,104 --> 00:56:05,288 아주 멋있고 아름다운 이미지들입니다. 799 00:56:05,288 --> 00:56:11,685 DeepDream의 코드를 Google이 온라인에 공개하였으니 여러분만의 아름다운 그림을 만들어보면 좋겠습니다. 800 00:56:11,685 --> 00:56:14,535 질문 있나요? 801 00:56:24,731 --> 00:56:28,252 질문은 "그레디언트를 어디에서 가져오는지" 입니다. 802 00:56:28,252 --> 00:56:33,318 앞서 말씀드렸듯, 1/(x^2)가 있을때 activation에 대한 그레디언트는 x입니다. 803 00:56:33,318 --> 00:56:44,477 따라서 그레디언트를 보낼때 activation 값 자체를 보내게 되면, 1/(x^2) 의 그레디언트를 계산하는 것과 동치입니다. 804 00:56:44,477 --> 00:56:49,665 그리고 이는 해당 레이어의 특징들(activations)의 norm을 최대화시키는 것과 동치입니다. 805 00:56:49,665 --> 00:56:56,511 하지만 대부분의 실제 구현은 이를 명시적으로 계산하지는 않고 그레디언트만 뒤로 보내줍니다. 806 00:56:56,511 --> 00:57:01,478 Feature inversion 이라는 아주 유용한 개념이 있습니다. 807 00:57:01,478 --> 00:57:07,687 이 방법 또한 네트워크의 다양한 레이어에서 이미지의 어떤 요소들을 포착하고 있는지를 짐작할 수 있게 해줍니다. 808 00:57:07,687 --> 00:57:12,220 방법은 다음과 같습니다. 어떤 이미지가 있고, 이 이미지를 네트워크에 통과시킵니다. 809 00:57:12,220 --> 00:57:15,832 그리고 네트워크를 통과시킨 특징(activation map)을 저장해둡니다. 810 00:57:15,832 --> 00:57:20,283 그리고 이제는 이 특징(activation map) 만 가지고 이미지를 재구성해 볼 것입니다. 811 00:57:20,283 --> 00:57:31,074 해당 레이어의 특징 벡터로부터 이미지를 재구성해보면, 이미지의 어떤 정보가 특징 벡터에서 포착되는지를 짐작할 수 있을 것입니다. 812 00:57:31,074 --> 00:57:34,191 이 방법에서 또한 regularizer를 추가한 gradient ascent를 이용합니다. 813 00:57:34,191 --> 00:57:41,709 스코어를 최대화시키는 것 대신, 특징 벡터간의 거리를 최소화시키는 방법을 이용합니다. 814 00:57:41,709 --> 00:57:50,014 기존에 계산해 놓은 특징 벡터와, 새롭게 생성한 이미지로 계산한 특징벡터 간의 거리를 측정하는 것입니다. 815 00:57:50,014 --> 00:57:56,856 여러분이 과제에서 보겠지만, 여기 사람들이 자주 사용하는 regularizer인 total vatication이 있습니다. 816 00:57:56,856 --> 00:58:05,954 Total variation regularizer은 상하좌우 인접 픽셀 간의 차이에 대한 패널티를 부여합니다. 817 00:58:05,954 --> 00:58:09,956 생성된 이미지가 자연스러운 이미지가 되도록 해줍니다. 818 00:58:09,956 --> 00:58:16,369 Feature inversion을 통한 시각화 예제를 살펴봅시다. 왼쪽은 원본 이미지입니다. 819 00:58:16,369 --> 00:58:18,294 코끼리 이미지와 과일 이미지가 있습니다. 820 00:58:18,294 --> 00:58:22,458 이 이미지를 VGG-16에 통과시켜봅시다. 821 00:58:22,458 --> 00:58:30,013 그리고 특징 맵을 기록하고, 기록된 특징 맵과 부합하도록 하는 새로운 이미지를 합성합니다. 822 00:58:30,013 --> 00:58:37,534 다양한 레이어를 이용해서 합성한 이미지들을 통해서, 얼마나 많은 정보들이 저장되어 있는지를 짐작해 볼 수 있습니다. 823 00:58:37,534 --> 00:58:43,849 가령 VGG-16 의 relu2_2를 거쳐서 나온 특징 벡터를 가지고 이미지를 재구성해보면 824 00:58:43,849 --> 00:58:46,628 이미지가 거의 완벽하게 재구성됨을 알 수 있습니다. 825 00:58:46,628 --> 00:58:52,664 이를 통해, relu2_2 에서는 이미지 정보를 엄청 많이 날려버리지는 않는다는 사실을 알 수 있습니다. 826 00:58:52,664 --> 00:58:58,593 자 그럼 이제 네트워크의 조금 더 깊은 곳을 살펴봅시다. relu4_3 과 relu5_1을 가지고 재구성해 보겠습니다. 827 00:58:58,593 --> 00:59:05,488 재구성된 이미지를 보면 이미지의 공간적인 구조는 잘 유지하고 있다는 것을 알 수 있습니다. 828 00:59:05,488 --> 00:59:09,684 재구성된 이미지만 봐도 코끼리인지, 바나나인지, 사과인지 우리 눈으로도 구별할 수 있습니다. 829 00:59:09,684 --> 00:59:16,427 하지만 디테일은 많이 죽었습니다. 정확히 어떤 픽셀인지, 어떤 색인지, 텍스터가 정확히 어떤지를 알아보기 힘듭니다. 830 00:59:16,427 --> 00:59:20,923 그런 낮은 레벨의 디테일들은 네트워크가 깊어질수록 손질됨을 알 수 있습니다. 831 00:59:20,923 --> 00:59:29,153 이를 통해서, 네트워크가 깊어질수록 픽셀 값이 정확히 얼마인지 와 같은 저 수준의 정보들은 전부 사라지고, 대신에 832 00:59:29,153 --> 00:59:38,109 색이나 텍스처와 같은 미세한 변화에 더 강인한 의미론적 정보들만을 유지하려 하는 것일지 모릅니다. 833 00:59:38,109 --> 00:59:42,835 우리는 지금까지 계속 Style transfer를 배우기 위한 준비단계에 있습니다. 834 00:59:42,835 --> 00:59:51,029 Style transfer와 feature inversion 외에도 텍스처 합성과 관련된 문제들도 살펴볼 필요가 있습니다. 835 00:59:51,029 --> 00:59:55,112 텍스처 합성 문제는 컴퓨터 그래픽스 분야에서는 아주 오래된 문제입니다. 836 00:59:55,112 --> 01:00:05,792 문제는, 가령 여기 보이시는 비늘 무늬와 같은 입력 텍스처 패치가 있을 때, 동일한 텍스처인 더 큰 패치를 생성하는 것입니다. 837 01:00:05,792 --> 01:00:12,056 가령 여기 보시는 그림과 같이 입력 패치와 비슷한 비늘 패턴을 가진 더 큰 이미지를 생성하는 것입니다. 838 01:00:12,056 --> 01:00:15,986 다시 말씀드리지만 텍스처 합성은 컴퓨터 그래픽스에서 아주 오래된 문제입니다. 839 01:00:15,986 --> 01:00:19,720 nearest neighbor를 통한 텍스처 합성 방법들도 상당히 좋은 편입니다. 840 01:00:19,720 --> 01:00:21,659 이 방법에는 신경망을 사용하지 않죠 841 01:00:21,659 --> 01:00:27,792 이 간단한 알고리즘은 신경망 대신에 scan line을 따라서 한 픽셀씩 이미지를 생성해 나가는 방식입니다. 842 01:00:27,792 --> 01:00:34,742 이 방법은 현재 생성해야 할 픽셀 주변의 이미 생성된 픽셀들을 살펴봅니다. 843 01:00:34,742 --> 01:00:41,934 그리고 입력 패치에서 가장 가까운 픽셀을 계산하여 입력 패치로부터 한 픽셀을 복사해 넣는 방식이죠 844 01:00:41,934 --> 01:00:48,889 더 자세히 알 필요는 없습니다. 텍스처 합성 문제를 위한 고전적인 방법들이 아주 많다는 사실만 알아두시면 됩니다. 845 01:00:48,889 --> 01:00:52,749 기본적으로 텍스처 합성은 신경망 없이도 할 수 있습니다. 846 01:00:52,749 --> 01:00:59,915 앞서 말씀드린 고전적인 방법들은 간단한 텍스처를 합성하는데는 큰 문제가 없습니다. 847 01:00:59,915 --> 01:01:08,970 하지만 조금 더 복잡한 텍스처에서는 상황이 조금 다릅니다. 단순하게 입력 패치에서 복사하는 방식은 잘 동작하지 않습니다. 848 01:01:08,970 --> 01:01:16,494 2015년에 신경망을 활용해서 텍스처 합성 문제는 푸려는 시도가 처음 있었습니다. 849 01:01:16,494 --> 01:01:24,753 이 방법은 우리가 앞서 살펴본 특징 맵을 이용한 gradient ascent 방법도 상당히 유사합니다. 850 01:01:24,753 --> 01:01:30,558 이 방법은 Neural texture synthesis 를 구현하기 위해서 Gram matrix라는 개념을 이용합니다. 851 01:01:30,558 --> 01:01:36,372 이 방법에서는, 가령 여기 입력 텍스처로 자갈 사진이 있습니다. 852 01:01:36,372 --> 01:01:44,347 이 사진을 네트워크에 통과시킨 후, 네트워크의 특정 레이어에서 특징 맵을 가져옵니다. 853 01:01:44,347 --> 01:01:53,596 이렇게 가져온 특징 맵의 크기는 C x H x W 일 것입니다. 854 01:01:53,596 --> 01:01:56,515 H x W 그리드는 공간 정보는 가지고 있습니다. 855 01:01:56,515 --> 01:02:04,347 H x W 의 한 점에 있는 C차원 특징 벡터는 해당 지점에 존재하는 이미지의 특징을 담고 있다고 할 수 있습니다. 856 01:02:04,347 --> 01:02:10,179 이제 이 특징 맵을 가지고 입력 이미지의 텍스트 기술자(descriptor)를 계산할 것입니다. 857 01:02:10,179 --> 01:02:15,294 우선 특징 맵에서 서로 다른 두 개의 특징 벡터를 뽑아냅니다. (빨간 색, 파란 색) 858 01:02:15,294 --> 01:02:18,318 각 특징 열 벡터는 C차원 벡터입니다. 859 01:02:18,318 --> 01:02:23,390 이 두 벡터의 외적(outer product)을 계산해서 C x C 행렬을 만듭니다. 860 01:02:23,390 --> 01:02:30,333 이 C x C 행렬은 이미지 내 서로 다른 두 지점에 있는 특징들 간의 co-occurrence를 담고 있습니다. 861 01:02:30,333 --> 01:02:40,218 가령 C x C 행렬의 (i, j) 번째 요소의 값이 크다는 것은 두 입력 벡터의 i번째, j번째 요소가 모두 크다는 의미입니다. 862 01:02:40,218 --> 01:02:51,572 이를 통해 서로 다른 공간에서 동시에 활성회되는 특징이 무엇인지 2차 모멘트를 통해 어느정도 포착해 낼 수 있는 것입니다. 863 01:02:51,572 --> 01:03:01,664 이 과정을 H x W 그리드에서 전부 수행해주고, 결과에 대한 평균을 계산해보면 C x C Gram matrix를 얻을 수 있습니다. 864 01:03:01,664 --> 01:03:06,323 그리고 이 결과를 입력 이미지의 텍스처를 기술하는 텍스처 기술자로 사용합니다. 865 01:03:06,323 --> 01:03:13,623 Gram matrix의 흥미로운 점은 공간 정보를 모두 날려버렸다는 것입니다. 866 01:03:13,623 --> 01:03:17,545 이미지의 각 지점에 해당하는 값들을 모두 평균화 시켰기 떄문입니다. 867 01:03:17,545 --> 01:03:21,863 공간 정보를 다 날려버린 대신에 특징들 간의 co-occurrence 만을 포착해 내고 있습니다. 868 01:03:21,863 --> 01:03:25,364 때문에 gram matrix는 텍스처 기술자로 아주 제격입니다. 869 01:03:25,364 --> 01:03:27,640 또한 계산도 아주 효율적입니다. 870 01:03:27,640 --> 01:03:39,682 C x H x W 차원의 3차원 텐서가 있다고 해도 행렬을 C x (HW)로 바꾼 다음에 한 번에 계산할 수 있습니다. 매우 효율적입니다. 871 01:03:39,682 --> 01:03:45,417 혹시, 왜 제대로된 공분산 행렬을 쓰지 않고 이런 허접한 gram matrix를 사용하는지 궁금하실 수도 있습니다. 872 01:03:45,417 --> 01:03:51,845 물론 공분산 행렬을 써도 무방하고, 실제로 동작도 잘 합니다. 하지만 공분한 행렬을 계산하는 것 자체가 비용이 너무 큽니다. 873 01:03:51,845 --> 01:03:55,203 따라서 실제로 사람들은 공분산 행렬 보다는 gram matrix를 선호하는 편입니다. 874 01:03:55,203 --> 01:04:06,916 자 이제 텍스처 기술자를 만들었으니 이미지를 생성할 차례입니다. 이는 gradient ascent procedure와 유사한 과정을 거칩니다. 875 01:04:06,916 --> 01:04:10,913 텍스처 합성도, 앞서 슬라이드에서 접했던 특징 재구성(feature reconstruction)와 유사합니다. 876 01:04:10,913 --> 01:04:20,883 다만 입력 이미지의 특징맵 전체를 재구성하기 보다는 gram matrix를 재구성하도록 하는 것입니다. 877 01:04:20,883 --> 01:04:25,969 실제로 거치는 단계는, 우선 pretrained model를 다운로드 받습니다. feature inversion에서 했던 것 처럼. 878 01:04:25,969 --> 01:04:28,720 많은 사람들이 VGG 네트워크를 선호합니다. 879 01:04:28,720 --> 01:04:38,553 그리고 이미지를 VGG에 통과시키고 다양한 레이어에서 gram matrix를 계산합니다. 880 01:04:38,553 --> 01:04:47,414 그리고 생성해야 할 이미지를 랜덤으로 초기화시키고, 그 다음 과정 부터는 gradient ascent와 유사합니다. 881 01:04:47,414 --> 01:04:52,530 다시, 우선 이미지를 VGG에 통과시킵니다. 그리고 여러 레이어에서 gram matrix를 계산합니다. 882 01:04:52,530 --> 01:05:00,833 그리고 원본 이미지와 생성된 이미지의 gram matrix 간의 차이를 L2 norm을 이용해 Loss로 계산합니다. 883 01:05:00,833 --> 01:05:06,025 그리고 Loss를 backprob을 통해 생성된 이미지의 픽셀의 그레디언트를 계산합니다. 884 01:05:06,025 --> 01:05:09,273 그리고 gradient ascent 를 통해 이미지의 픽셀을 조금씩 업데이트 합니다. 885 01:05:09,273 --> 01:05:17,071 이 단계을 여러번 반복합니다. 다시 앞 단계로 가서 gram matrix를 계산하고, Loss를 계산하고 backprob합니다. 886 01:05:17,071 --> 01:05:22,702 이 과정을 거치면 결국 입력 텍스처와 유사한 아주 잘 텍스처를 만들어낼 수 있습니다. 887 01:05:22,702 --> 01:05:30,022 NIP'15에 실린 논문은 독일의 한 연구소에서 나왔습니다. 텍스처 합성 결과가 아주 뛰어납니다. 888 01:05:30,022 --> 01:05:33,531 맨 위 이미지를 보시면 네가지의 서로 다른 입력 텍스처를 보실 수 있습니다. 889 01:05:33,531 --> 01:05:41,133 그리고 아래 쪽은 gram matix를 이용한 텍스터 합성을 보여줍니다. 890 01:05:41,133 --> 01:05:45,681 pretrained CNN의 다양한 레이어에서 gram matrix 를 계산한 결과입니다. 891 01:05:45,681 --> 01:05:56,965 얕은 레이어에서의 결과를 보면, 얼룩 얼룩한 이미지가 색상은 잘 유지하고 있지만 공간적인 구조는 잘 살리지 못합니다. 892 01:05:56,965 --> 01:06:06,935 레이어가 더 깊어질수록, 이미지의 더 큼지막한 패턴들을 아주 잘 재구성해 내는 것을 보실 수 있습니다. 893 01:06:06,935 --> 01:06:10,107 가령 여기 자갈이나 크렌베리를 보면 아주 잘 만들어졌죠 894 01:06:10,107 --> 01:06:17,677 결과가 상당히 좋습니다. 입력 패치의 패턴과 아주 유사한 새로운 이미지를 아주 잘 합성해 낼 수 있습니다. 895 01:06:17,677 --> 01:06:21,445 앞서 보여드린 고전적인 픽셀 기반의 방법과는 확연히 다른 결과들을 보실 수 있습니다. 896 01:06:21,445 --> 01:06:22,528 질문 있나요? 897 01:06:28,481 --> 01:06:30,847 질문은 "보통 Loss를 어느 레이어에서 계산하는지" 입니다. 898 01:06:30,847 --> 01:06:40,285 일반적으로는 gram matrix를 다양한 레이어에서 계산하고 가중 합을 통해 최종 loss를 구합니다. 899 01:06:40,285 --> 01:06:47,940 현재 보시는 슬라이드의 경우에는, 각 레이어의 특징을 강조하기 위해서, 오로지 한 레이어로만 gram matrix를 계산한 것입니다. 900 01:06:47,940 --> 01:06:52,999 이 논문 이후로 아주 놀라운 아이디어가 등장하게 됩니다. 901 01:06:52,999 --> 01:07:01,417 이 텍스처 합성을 자갈이나 크렌베리가 아니라 예술작품에 적용하면 어떻게 될까요? 902 01:07:01,417 --> 01:07:03,748 그래서, 예를 들어, 당신이... 903 01:07:03,748 --> 01:07:10,333 자 우선, gram matrix를 이용한 텍스처 합성은 그대로 가져갑니다. 904 01:07:10,333 --> 01:07:14,656 여기에 Starry night(Van Gogh) 이나 Muse(Picasso) 를 텍스처 입력으로 사용하면 어떻게 될까요? 905 01:07:14,656 --> 01:07:19,759 이들을 입력 텍스처로 두고 같은 알고리즘을 수행합니다. 906 01:07:19,759 --> 01:07:25,683 생성된 이미지를 보면, 이들은 예술 작품의 아주 흥미로운 부분들을 재구성해 내는 경향을 알 수 있습니다. 907 01:07:25,683 --> 01:07:34,616 texture synthesis와 feature inversion 을 조합하면 아주 흥미로운 일이 벌어집니다. 908 01:07:34,616 --> 01:07:38,988 아 아이디어가 바로 style transfer 입니다. 909 01:07:38,988 --> 01:07:42,716 Style transfer에서는 입력이 두가지입니다. 910 01:07:42,716 --> 01:07:49,813 Content Image는 네트워크에게 우리의 최종 이미지가 어떻게 "생겼으면 좋겠는지" 를 알려줍니다. 911 01:07:49,813 --> 01:07:55,499 Style Image는 최종 이미지의 "텍스처가 어땠으면 좋겠는지" 을 알려줍니다. 912 01:07:55,499 --> 01:08:02,596 최종 이미지는 content image의 feature reconstruction loss도 최소화하고(1), 913 01:08:02,596 --> 01:08:05,661 Style image의 gram matrix loss도 최소화하는 방식으로 최적화하여 생성해 냅니다. 914 01:08:05,661 --> 01:08:14,353 이 두가지 Loss를 동시에 활용하면, style image 스러운 화풍의 content image가 생성됩니다. 915 01:08:14,353 --> 01:08:18,317 아주 멋있는 결과입니다. 아주 아름다운 이미지를 얻을 수 있습니다. 916 01:08:18,317 --> 01:08:26,384 네트워크에 content/style 이미지를 네트워크에 통과시키고 gram matrix와 feature map을 계산합니다. 917 01:08:26,384 --> 01:08:29,332 최종 출력 이미지는 랜덤 노이즈로 초기화시킵니다. 918 01:08:29,332 --> 01:08:38,264 forward/backward를 반복하여 계산하고 gradient ascent 를 이용해서 이미지를 업데이트합니다. 919 01:08:38,265 --> 01:08:43,247 수 백번정도 반복하면 아주 아름다운 이미지를 얻을 수 있게 됩니다. 920 01:08:43,247 --> 01:08:48,965 제 github에 실제 구현이 있습니다. 사람들이 많이 사용하는데요, 아주 멋집니다. 921 01:08:48,965 --> 01:08:54,609 Style Transfer는 DeepDream에 비해서 이미지를 생성할 때 컨트롤할 만한 것들이 더 많습니다. 922 01:08:54,609 --> 01:09:00,544 DeepDream의 경우에는 어떤 것들을 만들어낼지 컨트롤할 만한 요소가 많이 부족합니다. 923 01:09:00,544 --> 01:09:06,500 네트워크에 레이어와 반복 횟수정도만 조절하면 "개 달팽이(dog slug)"가 이미지 전체에 퍼질 뿐입니다. 924 01:09:06,500 --> 01:09:11,228 반면 Style Transfer의 경우 원하는 결과를 만들기 위해 정밀 조절한 것들이 조금 더 많습니다. 925 01:09:11,228 --> 01:09:19,099 동일한 content image라고 할지라도 다양한 style images 를 고르게 되면 전혀 다른 이미지들이 생성됩니다. 926 01:09:19,099 --> 01:09:30,349 하이퍼파라미터도 자유롭게 조정할 수 있습니다. style/content loss의 joint loss이기 때문이죠 927 01:09:30,350 --> 01:09:39,468 style/content loss간의 가중치를 조절하면, 내가 어디에 더 집중해서 만들 것인지를 조절할 수 있습니다. 928 01:09:39,469 --> 01:09:41,647 또 다른 하이퍼파라이터도 존재합니다. 929 01:09:41,647 --> 01:09:45,707 가령 gram matrix를 계산하기 앞서 style image를 리사이징 해서 넣어준다면 930 01:09:45,707 --> 01:09:52,344 Style image로부터 재구성된 특징들의 스케일을 여러분 마음대로 조절할 수 있을 것입니다. 931 01:09:52,344 --> 01:09:58,976 여기 보이는 이미지들은 다른 것들은 전부 같은 세팅이고 다만 style image의 사이즈만 달라진 경우입니다. 932 01:09:58,976 --> 01:10:04,263 Style image의 사이즈를 조절하는 것이 조절할 수 있는 또 하나의 축이 될 수 있습니다. 933 01:10:04,263 --> 01:10:07,670 또한 여러 장의 style images를 가지고 style transfer를 할 수도 있습니다. 934 01:10:07,670 --> 01:10:13,431 동시에 여러 style loss의 gram matrix를 계산하는 것입니다. 결과도 아주 좋습니다. 935 01:10:13,431 --> 01:10:25,105 앞서 DeepDream에서 multi-scale processing을 통해 아주 멋진 고해상도 이미지를 얻을 수 있었습니다. 936 01:10:25,105 --> 01:10:29,330 multi-scale processing을 style transfer에도 적용해 볼 수 있습니다. 937 01:10:29,330 --> 01:10:40,867 이 이미지는 Starry night로 랜더링된 4K Stanford 이미지입니다. 938 01:10:40,867 --> 01:10:42,652 사실 고해상도 이미지를 만드는 것은 계산량이 상당합니다. 939 01:10:42,652 --> 01:10:47,074 4K 이미지를 위해 GPU 네 개를 사용했습니다. 아주 비싼 연산입니다. 940 01:10:47,074 --> 01:10:53,666 이는 동일한 content image를 가지고 다른 style image를 적용한 것입니다. 고해상도죠 941 01:10:53,666 --> 01:11:01,168 또 다른 재밌는 방법도 있습니다. 사실 Style Transfer와 DeepDream을 조합해 볼 수도 있습니다. 942 01:11:01,168 --> 01:11:09,017 content loss + style loss + deepdream loss( norm 최대화) 를 조합하는 것입니다. 943 01:11:09,017 --> 01:11:14,286 결과는 다음과 같습니다. "개 달팽이(dog slug)" 가 사방에 퍼져있는 Van Gogh 그림입니다. 944 01:11:14,286 --> 01:11:15,858 [웃음] 945 01:11:15,858 --> 01:11:18,466 아주 재밌습니다. 946 01:11:18,466 --> 01:11:23,012 Style Stranfer 알고리즘의 가장 큰 단점은 아주 느리다는 것입니다. 947 01:11:23,012 --> 01:11:30,164 이런 이미지를 만들어 내려면 backward/forward를 아주 많이 반복해야 합니다. 948 01:11:30,164 --> 01:11:38,200 게다가 앞서 보여드린 4K 이미지를 만드려면 메모리와 계산량이 엄청나게 큽니다. 949 01:11:38,200 --> 01:11:46,340 엄청 좋은 GPU를 쓰더라도 이미지 한장을 만드는데 수십 분이 요소됩니다. 950 01:11:46,340 --> 01:11:50,320 따라서 실제로 적용하기는 힘듭니다. 951 01:11:50,320 --> 01:11:54,874 해결책이 있다면, Style tranfer를 위한 또 다른 네트워크를 학습시키는 것입니다. 952 01:11:54,874 --> 01:12:03,164 2016년에 나온 논문입니다. 애초에 Style image를 고정시켜 놓습니다. 이 경우 Starry night 입니다. 953 01:12:03,164 --> 01:12:08,034 이 방법은 합성하고자 하는 이미지의 최적화를 전부 수행하는 것이 아니라 954 01:12:08,034 --> 01:12:15,748 Content image만을 입력으로 받아서 결과를 출력할 수 있는 단일 네트워크를 학습시키는 방법입니다. 955 01:12:15,748 --> 01:12:26,848 이 네트워크의 학습 시에는, content/style loss를 동시에 학습시키고 네트워크의 가중치를 업데이트합니다. 956 01:12:26,848 --> 01:12:36,148 학습은 몇 시간이 걸릴 수 있지만, 한번 학습시키고 나면 이미지를 네트워크에 통과시키면 결과가 바로 나올 수 있습니다. 957 01:12:36,148 --> 01:12:49,880 이 코드는 온라인에 있습니다. 영상 퀄리티는 기존의 방법과 거의 유사하면서도, 몇천배 빠르게 동작합니다. 958 01:12:49,880 --> 01:12:54,990 여러분이 보고계신 이 데모는 제가 웹캠으로 직접 돌려본 것입니다. 959 01:12:54,990 --> 01:13:05,476 이 네트워크가 아주 효율적이기 때문에 좋은 GPU을 사용하면 네 가지 스타일을 동시에 돌려볼 수도 있을 것입니다. 960 01:13:05,476 --> 01:13:12,650 러시아에서 나온 논문도 있습니다. 유사한 논문이고 결과도 아주 좋습니다. 961 01:13:12,650 --> 01:13:15,392 알고리즘을 조금 변형한 방법도 있습니다. 962 01:13:15,392 --> 01:13:25,450 앞서 보여드린 이 네트워크는 앞서 배웠던 세그멘데이션 네트워크와도 아주 유사하게 생겼습니다. 963 01:13:25,450 --> 01:13:37,678 Sementic segmentation 에서는 다운 샘플링을 여러 번 진행하고 transposed conv로 업샘플링을 합니다. 964 01:13:37,678 --> 01:13:45,244 Segmentic segmentation과 다른 점이라고는 출력이 RGB 이미지라는 점입니다. 965 01:13:45,244 --> 01:13:48,540 그리고 네트워크 중간에 batch norm이 들어갑니다. 966 01:13:48,540 --> 01:13:56,027 이 논문에서는 batch norm 대신에 instance norm을 사용해서 더 좋은 결과를 끌어냈습니다. 967 01:13:56,027 --> 01:14:05,500 지금까지 말씀드린 방식들의 단점이 있다면 네트워크 하나당 하나의 Style Transfer 밖에 할 수 덦다는 점입니다. 968 01:14:05,500 --> 01:14:10,433 다양한 Style을 위해서 서로 다른 네트워크를 만드는 일은 상당히 비용이 큰 작업입니다. 969 01:14:10,433 --> 01:14:21,178 아주 최근에 Google 에서 나온 논문은, 하나의 네트워크로 다양한 Style을 생성해낼 수 있는 방법을 제안했습니다. 970 01:14:21,178 --> 01:14:28,034 하나의 네트워크만 학습시켜서 다양한 Style result를 만들어낼 수 있는 방법입니다. 971 01:14:28,034 --> 01:14:36,477 네트워크 입력으로 content image와 style image를 동시에 넣는 방식을 통해서 다양한 스타일을 만들어낼 수 있습니다. 972 01:14:36,477 --> 01:14:39,365 이 네트워크 또한 실시간으로 동작할 수 있습니다. 973 01:14:39,365 --> 01:14:44,442 동일한 알고리즘은 하나의 네트워크 만으로 실시간 style blending 또한 가능합니다. 974 01:14:44,442 --> 01:14:52,458 네 가지 서로 다른 style을 학습시키면 이 네 가지 style을 섞어버릴 수도 있습니다. 975 01:14:52,458 --> 01:15:01,976 이러한 종류의 real-time style transfer 방법들은 아주 다양한 응용이 가능하며 실제로 많이 사용되고 있습니다. 976 01:15:01,976 --> 01:15:04,071 오늘 배운 내용을 요약해봅시다. 977 01:15:04,071 --> 01:15:08,113 우리는 오늘 CNN representations을 이해할 수있는 다양한 방법들을 배웠습니다. 978 01:15:08,113 --> 01:15:10,190 우선 activation 기반의 방법들이 있었습니다. 979 01:15:10,190 --> 01:15:14,220 nearest neighbor, dimensionality reduction maximal patches, occlusion images 등이죠 980 01:15:14,220 --> 01:15:18,316 Activation values를 기반으로 해당 특징이 무엇을 찾고있는지를 이해하는 방법이었습니다. 981 01:15:18,316 --> 01:15:20,461 우리는 또한 gradient 기반의 방법도 배웠습니다. 982 01:15:20,461 --> 01:15:27,127 gradients을 이용해서 새로운 이미지를 만들어내는 방법이었습니다. 983 01:15:27,127 --> 01:15:30,417 saliency maps, class visualizations, fooling images, feature inversion이 있었죠 984 01:15:30,417 --> 01:15:37,997 그리고 아주 멋있는 이미지들을 생성해내는 Style Transfer/DeepDream을 알아보았습니다. 985 01:15:37,997 --> 01:15:40,397 다음 시간에는 unsupervised learning에 대해서 배워보겠습니다. 986 01:15:40,397 --> 01:15:45,834 Autoencoders, Variational Autoencoders(VAE), generative adversarial networks(GAN) 을 배워보겠습니다.